Skip to content

Commit 2cb5ca7

Browse files
authored
feat(search,resources): search for docs, migrate to mcp resources (#74)
* docs, add new resources, fetchDocs/componentSchemas combined into usePatternFlyDocs * options.defaults, docsHost disabled, add resourceModules and maxDocs, rename/increase memo settings * resource.patternFlyContext, add general PatternFly development context * resource.patternFlyDocsIndex, add documentation index * resource.patternFlyDocsTemplate, add dynamic documentation resource patternfly://docs/{name} * resource.patternFlySchemasIndex, add component names index for schemas * resource.patternFlySchemasTemplate, add JSON Schema resource patternfly://schemas/{name} * server.getResources, processDocs refactor for structured response, promise queue and limit, refactor for resolve paths * server.helpers, stringJoin, isAsync, isUrl, and timeoutFunction added * server.resources, add composeResources for external resource registration * server.search, tools, expand fuzzy search typing, annotations * server, register built-ins and integrate resource processing into lifecycle, timeout for failed transport connections * tool.componentSchemas, deprecate in favor of usePatternFlyDocs * tool.fetchDocs, remove duplicated functionality in favor of usePatternFlyDocs * tool.patternFlyDocs, refactor description, use shared resource logic, handle names and URLs * tool.searchPatternFlyDocs, fuzzy search for docs and components
1 parent e7e5c64 commit 2cb5ca7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2644
-860
lines changed

README.md

Lines changed: 51 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -49,37 +49,47 @@ npx @patternfly/patternfly-mcp
4949

5050
## Usage
5151

52-
The MCP server can communicate over **stdio** (default) or **HTTP** transport. It provides access to PatternFly documentation through built-in tools.
52+
The MCP server tools are focused on being a resource library for PatternFly. Server tools are extensible by design and intended to be used in conjunction with the available MCP resources.
5353

5454
### Built-in Tools
5555

56-
All tools accept an argument named `urlList` (array of strings) or `componentName` (string).
56+
#### Tool: searchPatternFlyDocs
57+
Use this to search for PatternFly documentation URLs and component names. Accepts partial string matches or `*` to list all available components. From the content, you can select specific URLs and component names to use with `usePatternFlyDocs`
58+
59+
- **Parameters**: `searchQuery`: `string` (required)
5760

5861
#### Tool: usePatternFlyDocs
59-
Use this to fetch high-level index content (for example, a local `README.md` that contains relevant links, or `llms.txt` files in docs-host mode). From that content, you can select specific URLs to pass to `fetchDocs`.
62+
Fetch full documentation and component JSON schemas for specific PatternFly URLs or component names.
6063

61-
- **Parameters**: `urlList`: `string[]` (required)
64+
> **Feature**: This tool automatically detects if a URL belongs to a component (or if a "name" is provided) and appends its machine-readable JSON schema (props, types, validation) to the response, providing a fused context of human-readable docs and technical specs.
6265
63-
#### Tool: fetchDocs
64-
Use this to fetch one or more specific documentation pages (e.g., concrete design guidelines or accessibility pages) after you’ve identified them via `usePatternFlyDocs`.
66+
- **Parameters**: _Parameters are mutually exclusive. Provide either `name` OR `urlList` not both._
67+
- `name`: `string` (optional) - The name of the PatternFly component (e.g., "Button", "Modal"). **Recommended** for known component lookups.
68+
- `urlList`: `string[]` (optional) - A list of specific documentation URLs discovered via `searchPatternFlyDocs`.
6569

66-
- **Parameters**: `urlList`: `string[]` (required)
70+
#### Removed: ~~Tool: fetchDocs~~
71+
> "fetchDocs" has been integrated into "usePatternFlyDocs."
6772
68-
#### Tool: componentSchemas
69-
Use this to fetch the JSON Schema for a specific PatternFly component.
73+
~~Use this to fetch one or more specific documentation pages (e.g., concrete design guidelines or accessibility pages) after you’ve identified them via `usePatternFlyDocs`.~~
7074

71-
- **Parameters**: `componentName`: `string` (required)
75+
- ~~**Parameters**: `urlList`: `string[]` (required)~~
7276

73-
### Docs-host mode (local llms.txt mode)
77+
#### Deprecated: ~~Tool: componentSchemas~~
78+
> "componentSchemas" has been integrated into "usePatternFlyDocs."
7479
75-
If you run the server with `--docs-host`, local paths you pass in `urlList` are resolved relative to the `llms-files` folder at the repository root. This is useful when you have pre-curated `llms.txt` files locally.
80+
~~Use this to fetch the JSON Schema for a specific PatternFly component.~~
7681

77-
Example:
78-
```bash
79-
npx @patternfly/patternfly-mcp --docs-host
80-
```
82+
- ~~**Parameters**: `componentName`: `string` (required)~~
83+
84+
### Built-in Resources
85+
86+
The server exposes a resource-centric architecture via the `patternfly://` URI scheme:
8187

82-
Then, passing a local path such as `react-core/6.0.0/llms.txt` in `urlList` will load from `llms-files/react-core/6.0.0/llms.txt`.
88+
- **`patternfly://context`**: General PatternFly development context and high-level rules.
89+
- **`patternfly://docs/index`**: Index of all available documentation pages.
90+
- **`patternfly://docs/{name}`**: Documentation for a specific component (e.g., `patternfly://docs/Button`).
91+
- **`patternfly://schemas/index`**: Index of all available component schemas.
92+
- **`patternfly://schemas/{name}`**: JSON Schema for a specific component (e.g., `patternfly://schemas/Button`).
8393

8494
### MCP Client Configuration
8595

@@ -111,19 +121,6 @@ Most MCP clients use a JSON configuration to specify how to start this server. B
111121
}
112122
```
113123

114-
#### Docs-host mode
115-
```json
116-
{
117-
"mcpServers": {
118-
"patternfly-docs": {
119-
"command": "npx",
120-
"args": ["-y", "@patternfly/patternfly-mcp@latest", "--docs-host"],
121-
"description": "PatternFly docs (docs-host mode)"
122-
}
123-
}
124-
}
125-
```
126-
127124
#### Custom local tool
128125

129126
```json
@@ -173,6 +170,30 @@ Example:
173170
npx @patternfly/patternfly-mcp --log-stderr --log-level debug
174171
```
175172

173+
### Disabled: ~~Docs-host mode (local llms.txt mode)~~
174+
175+
> Docs-host mode will be removed or replaced in a future release.
176+
>
177+
> Docs-host mode was intended to be a more efficient way for accessing text file versions of PatternFly documentation and link
178+
> resources. That effort was intended to help load times and token counts while attempting to account for future API work.
179+
> Docs-host mode documentation and links have experienced drift with recent updates to PatternFly resources. That drift combined
180+
> with the introduction of MCP server resources concludes in disabling Docs-host mode while we evaluate its removal or replacement.
181+
>
182+
> If you have been using Docs-host mode, there's a probability you've been leveraging model inference instead of PatternFly
183+
> documentation. You can continue passing the `--docs-host` flag, it will not break the CLI, but it will no-longer affect how the
184+
> PatternFly MCP server loads documentation and link resources.
185+
186+
~~If you run the server with `--docs-host`, local paths you pass in `urlList` are resolved relative to the `llms-files` folder at the repository root. This is useful when you have pre-curated `llms.txt` files locally.~~
187+
188+
- `--docs-host`: Running this flag produces no results. ~~Local paths you pass in `urlList` are resolved relative to the `llms-files` folder.~~
189+
190+
Example:
191+
```bash
192+
npx @patternfly/patternfly-mcp --docs-host
193+
```
194+
195+
~~Then, passing a local path such as `react-core/6.0.0/llms.txt` in `urlList` will load from `llms-files/react-core/6.0.0/llms.txt`.~~
196+
176197
### MCP Tool Plugins
177198

178199
You can extend the server's capabilities by loading **Tool Plugins** at startup. These plugins run out‑of‑process in an isolated **Tools Host** (Node.js >= 22) to ensure security and stability.

src/__tests__/__snapshots__/options.defaults.test.ts.snap

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ exports[`options defaults should return specific properties: defaults 1`] = `
2121
"stderr": false,
2222
"transport": "stdio",
2323
},
24+
"maxDocsToLoad": 500,
2425
"name": "@patternfly/patternfly-mcp",
2526
"nodeVersion": 22,
2627
"pfExternal": "https://raw.githubusercontent.com/patternfly/patternfly-org/fb05713aba75998b5ecf5299ee3c1a259119bd74/packages/documentation-site/patternfly-docs/content",
@@ -38,6 +39,7 @@ exports[`options defaults should return specific properties: defaults 1`] = `
3839
"loadTimeoutMs": 5000,
3940
},
4041
"pluginIsolation": "strict",
42+
"recommendedMaxDocsToLoad": 15,
4143
"repoName": "patternfly-mcp",
4244
"resourceMemoOptions": {
4345
"default": {
@@ -54,6 +56,7 @@ exports[`options defaults should return specific properties: defaults 1`] = `
5456
"expire": 120000,
5557
},
5658
},
59+
"resourceModules": [],
5760
"separator": "
5861
5962
---
@@ -66,10 +69,10 @@ exports[`options defaults should return specific properties: defaults 1`] = `
6669
},
6770
},
6871
"toolMemoOptions": {
69-
"fetchDocs": {
72+
"searchPatternFlyDocs": {
7073
"cacheErrors": false,
71-
"cacheLimit": 15,
72-
"expire": 60000,
74+
"cacheLimit": 10,
75+
"expire": 600000,
7376
},
7477
"usePatternFlyDocs": {
7578
"cacheErrors": false,
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`patternFlyContextResource should have a consistent return structure: structure 1`] = `
4+
{
5+
"config": true,
6+
"handler": [Function],
7+
"name": "patternfly-context",
8+
"uri": "patternfly://context",
9+
}
10+
`;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`patternFlyDocsIndexResource should have a consistent return structure: structure 1`] = `
4+
{
5+
"config": true,
6+
"handler": [Function],
7+
"name": "patternfly-docs-index",
8+
"uri": "patternfly://docs/index",
9+
}
10+
`;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`patternFlyDocsTemplateResource should have a consistent return structure: structure 1`] = `
4+
{
5+
"config": true,
6+
"handler": [Function],
7+
"name": "patternfly-docs-template",
8+
"uri": ResourceTemplate {
9+
"_callbacks": {
10+
"list": undefined,
11+
},
12+
"_uriTemplate": UriTemplate {
13+
"parts": [
14+
"patternfly://docs/",
15+
{
16+
"exploded": false,
17+
"name": "name",
18+
"names": [
19+
"name",
20+
],
21+
"operator": "",
22+
},
23+
],
24+
"template": "patternfly://docs/{name}",
25+
},
26+
},
27+
}
28+
`;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`patternFlySchemasIndexResource should have a consistent return structure: structure 1`] = `
4+
{
5+
"config": true,
6+
"handler": [Function],
7+
"name": "patternfly-schemas-index",
8+
"uri": "patternfly://schemas/index",
9+
}
10+
`;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
2+
3+
exports[`patternFlySchemasTemplateResource should have a consistent return structure: structure 1`] = `
4+
{
5+
"config": true,
6+
"handler": [Function],
7+
"name": "patternfly-schemas-template",
8+
"uri": ResourceTemplate {
9+
"_callbacks": {
10+
"list": undefined,
11+
},
12+
"_uriTemplate": UriTemplate {
13+
"parts": [
14+
"patternfly://schemas/",
15+
{
16+
"exploded": false,
17+
"name": "name",
18+
"names": [
19+
"name",
20+
],
21+
"operator": "",
22+
},
23+
],
24+
"template": "patternfly://schemas/{name}",
25+
},
26+
},
27+
}
28+
`;
Lines changed: 83 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,100 @@
11
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
22

33
exports[`processDocsFunction should handle errors gracefully: errors 1`] = `
4-
"# Documentation from good-file.md
5-
6-
success content
7-
8-
---
9-
10-
❌ Failed to load bad-file.md: Error: File not found"
4+
[
5+
{
6+
"content": "success content",
7+
"isSuccess": true,
8+
"path": "good-file.md",
9+
"resolvedPath": "/good-file.md",
10+
},
11+
{
12+
"content": "❌ Failed to load bad-file.md: File not found",
13+
"isSuccess": false,
14+
"path": "bad-file.md",
15+
"resolvedPath": undefined,
16+
},
17+
]
1118
`;
1219

1320
exports[`processDocsFunction should process local and remote inputs, duplicate files and URLS 1`] = `
14-
"# Documentation from file.md
15-
16-
local file content
17-
18-
---
19-
20-
# Documentation from https://example.com/remote.md
21-
22-
fetched content"
21+
[
22+
{
23+
"content": "local file content",
24+
"isSuccess": true,
25+
"path": "file.md",
26+
"resolvedPath": "/file.md",
27+
},
28+
{
29+
"content": "fetched content",
30+
"isSuccess": true,
31+
"path": "https://example.com/remote.md",
32+
"resolvedPath": "https://example.com/remote.md",
33+
},
34+
]
2335
`;
2436

2537
exports[`processDocsFunction should process local and remote inputs, files and URLS 1`] = `
26-
"# Documentation from local-file.md
27-
28-
local file content
29-
30-
---
31-
32-
# Documentation from https://example.com/remote.md
33-
34-
fetched content"
38+
[
39+
{
40+
"content": "local file content",
41+
"isSuccess": true,
42+
"path": "local-file.md",
43+
"resolvedPath": "/local-file.md",
44+
},
45+
{
46+
"content": "fetched content",
47+
"isSuccess": true,
48+
"path": "https://example.com/remote.md",
49+
"resolvedPath": "https://example.com/remote.md",
50+
},
51+
]
3552
`;
3653

3754
exports[`processDocsFunction should process local and remote inputs, filter empty strings 1`] = `
38-
"# Documentation from file.md
39-
40-
local file content
55+
[
56+
{
57+
"content": "local file content",
58+
"isSuccess": true,
59+
"path": "file.md",
60+
"resolvedPath": "/file.md",
61+
},
62+
{
63+
"content": "local file content",
64+
"isSuccess": true,
65+
"path": "file2.md",
66+
"resolvedPath": "/file2.md",
67+
},
68+
]
69+
`;
4170

42-
---
71+
exports[`promiseQueue should execute promises in order: allSettled 1`] = `
72+
[
73+
{
74+
"status": "fulfilled",
75+
"value": {
76+
"content": "/dolor-sit.md",
77+
"resolvedPath": "/dolor-sit.md",
78+
},
79+
},
80+
{
81+
"reason": "https://example.com/remote.md",
82+
"status": "rejected",
83+
},
84+
{
85+
"status": "fulfilled",
86+
"value": {
87+
"content": "/lorem-ipsum.md",
88+
"resolvedPath": "/lorem-ipsum.md",
89+
},
90+
},
91+
]
92+
`;
4393

44-
# Documentation from file2.md
94+
exports[`resolveLocalPathFunction should return a consistent path, basic 1`] = `"/lorem-ipsum.md"`;
4595

46-
local file content"
47-
`;
96+
exports[`resolveLocalPathFunction should return a consistent path, url, file 1`] = `"file://someDirectory/dolor-sit.md"`;
4897

49-
exports[`resolveLocalPathFunction should return a consistent path, with docsHost false 1`] = `"documentation/README.md"`;
98+
exports[`resolveLocalPathFunction should return a consistent path, url, http 1`] = `"http://example.com/dolor-sit.md"`;
5099

51-
exports[`resolveLocalPathFunction should return a consistent path, with docsHost true 1`] = `"/llms-files/react-core/6.0.0/llms.txt"`;
100+
exports[`resolveLocalPathFunction should return a consistent path, url, https 1`] = `"https://example.com/dolor-sit.md"`;

0 commit comments

Comments
 (0)