Skip to content

Commit 4dc310a

Browse files
committed
feat: api integration
1 parent 77c9c40 commit 4dc310a

13 files changed

+463
-11
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ yarn-error.log*
77
# Build output
88
dist/
99
build/
10+
cache/
1011
*.tsbuildinfo
1112

1213
# Environment variables

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"type": "module",
77
"imports": {
88
"~docsCatalog": "./src/docs.json",
9+
"#buildDocs": "./dist/patternFly.buildDocs.js",
910
"#toolsHost": "./dist/server.toolsHost.js"
1011
},
1112
"exports": {
@@ -27,6 +28,7 @@
2728
"scripts": {
2829
"build": "npm run build:clean; npm run test:types; pkgroll",
2930
"build:clean": "rm -rf dist",
31+
"build:api": "node dist/cli.js --mode docs --log-stderr",
3032
"build:watch": "npm run build -- --watch",
3133
"release": "changelog --non-cc --link-url https://github.com/patternfly/patternfly-mcp.git",
3234
"start": "node dist/cli.js --log-stderr",

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,19 @@ exports[`options defaults should return specific properties: defaults 1`] = `
4141
"mode": "programmatic",
4242
"modeOptions": {
4343
"cli": {},
44+
"docs": {},
4445
"programmatic": {},
4546
"test": {},
4647
},
4748
"name": "@patternfly/patternfly-mcp",
4849
"nodeVersion": 22,
4950
"patternflyOptions": {
51+
"api": {
52+
"endpoints": {
53+
"v6": "https://patternfly-doc-core.pages.dev/api/v6",
54+
},
55+
"expireDays": 14,
56+
},
5057
"availableResourceVersions": [
5158
"6.0.0",
5259
],
@@ -70,6 +77,7 @@ exports[`options defaults should return specific properties: defaults 1`] = `
7077
},
7178
"urlWhitelist": [
7279
"https://patternfly.org",
80+
"https://patternfly-doc-core.pages.dev",
7381
"https://github.com/patternfly",
7482
"https://raw.githubusercontent.com/patternfly",
7583
],

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ exports[`parseCliOptions should attempt to parse args with --allowed-hosts 1`] =
1818
},
1919
"modeOptions": {
2020
"cli": {},
21+
"docs": {},
2122
"programmatic": {},
2223
"test": {},
2324
},
@@ -44,6 +45,7 @@ exports[`parseCliOptions should attempt to parse args with --allowed-origins 1`]
4445
},
4546
"modeOptions": {
4647
"cli": {},
48+
"docs": {},
4749
"programmatic": {},
4850
"test": {},
4951
},
@@ -67,6 +69,7 @@ exports[`parseCliOptions should attempt to parse args with --http and --host 1`]
6769
},
6870
"modeOptions": {
6971
"cli": {},
72+
"docs": {},
7073
"programmatic": {},
7174
"test": {},
7275
},
@@ -90,6 +93,7 @@ exports[`parseCliOptions should attempt to parse args with --http and --port 1`]
9093
},
9194
"modeOptions": {
9295
"cli": {},
96+
"docs": {},
9397
"programmatic": {},
9498
"test": {},
9599
},
@@ -113,6 +117,7 @@ exports[`parseCliOptions should attempt to parse args with --http and invalid --
113117
},
114118
"modeOptions": {
115119
"cli": {},
120+
"docs": {},
116121
"programmatic": {},
117122
"test": {},
118123
},
@@ -134,6 +139,7 @@ exports[`parseCliOptions should attempt to parse args with --http flag 1`] = `
134139
},
135140
"modeOptions": {
136141
"cli": {},
142+
"docs": {},
137143
"programmatic": {},
138144
"test": {},
139145
},
@@ -155,6 +161,7 @@ exports[`parseCliOptions should attempt to parse args with --log-level flag 1`]
155161
},
156162
"modeOptions": {
157163
"cli": {},
164+
"docs": {},
158165
"programmatic": {},
159166
"test": {},
160167
},
@@ -176,6 +183,7 @@ exports[`parseCliOptions should attempt to parse args with --log-stderr flag and
176183
},
177184
"modeOptions": {
178185
"cli": {},
186+
"docs": {},
179187
"programmatic": {},
180188
"test": {},
181189
},
@@ -197,6 +205,7 @@ exports[`parseCliOptions should attempt to parse args with --tool 1`] = `
197205
},
198206
"modeOptions": {
199207
"cli": {},
208+
"docs": {},
200209
"programmatic": {},
201210
"test": {},
202211
},
@@ -221,6 +230,7 @@ exports[`parseCliOptions should attempt to parse args with --verbose flag 1`] =
221230
},
222231
"modeOptions": {
223232
"cli": {},
233+
"docs": {},
224234
"programmatic": {},
225235
"test": {},
226236
},
@@ -242,6 +252,7 @@ exports[`parseCliOptions should attempt to parse args with --verbose flag and --
242252
},
243253
"modeOptions": {
244254
"cli": {},
255+
"docs": {},
245256
"programmatic": {},
246257
"test": {},
247258
},
@@ -263,6 +274,7 @@ exports[`parseCliOptions should attempt to parse args with other arguments 1`] =
263274
},
264275
"modeOptions": {
265276
"cli": {},
277+
"docs": {},
266278
"programmatic": {},
267279
"test": {},
268280
},

src/__tests__/api.json.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import apiJson from '../api.json';
2+
3+
describe('api.json', () => {
4+
it('should have a valid top-level generated timestamp (ISO date string)', () => {
5+
expect(apiJson.generated).toBeDefined();
6+
expect(typeof apiJson.generated).toBe('string');
7+
expect(apiJson.generated.length).toBeGreaterThan(0);
8+
9+
const rawDate = apiJson.generated;
10+
const parsedDate = Date.parse(rawDate);
11+
12+
expect(Number.isNaN(parsedDate)).toBe(false);
13+
14+
// Canonical ISO 8601 UTC form from Date.prototype.toISOString()
15+
expect(new Date(parsedDate).toISOString()).toBe(rawDate);
16+
});
17+
18+
it('should have a valid meta structure', () => {
19+
expect(apiJson.meta).toBeDefined();
20+
expect(apiJson.meta.totalEntries).toBeDefined();
21+
expect(apiJson.meta.totalDocs).toBeDefined();
22+
expect(apiJson.meta.source).toBe('patternfly-mcp-api');
23+
expect(apiJson.meta.lastBuildRun).toBeDefined();
24+
});
25+
26+
it('should have a docs object', () => {
27+
expect(apiJson.docs).toBeDefined();
28+
expect(typeof apiJson.docs).toBe('object');
29+
});
30+
});

src/api.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"version": "1",
3+
"generated": "2026-03-23T20:00:00.000Z",
4+
"meta": {
5+
"totalEntries": 0,
6+
"totalDocs": 0,
7+
"source": "patternfly-mcp-api",
8+
"lastBuildRun": "2026-03-23T20:00:00.000Z"
9+
},
10+
"docs": {}
11+
}

src/docs.embedded.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ interface PatternFlyMcpDocsCatalog {
3535
totalEntries: number;
3636
totalDocs: number;
3737
source: string;
38+
[key: string]: unknown;
3839
};
3940
docs: PatternFlyMcpDocsCatalogEntry
4041
}

src/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,22 @@ const main = async (
176176

177177
// Finalize exit policy after merging options
178178
updatedAllowProcessExit = allowProcessExit ?? mergedOptions.mode !== 'test';
179+
180+
// Handle documentation building mode
181+
if (mergedOptions.mode === 'docs') {
182+
const { createLogger } = await import('./logger');
183+
const { buildPatternFlyDocs } = await import('#buildDocs' as string);
184+
185+
createLogger();
186+
187+
const instance = await buildPatternFlyDocs(mergedOptions);
188+
189+
if (updatedAllowProcessExit) {
190+
process.exit(0);
191+
}
192+
193+
return instance as any;
194+
}
179195
} catch (error) {
180196
processExit('Set options error, failed to start server:', error);
181197
}

src/options.defaults.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { type ToolModule } from './server.toolsUser';
2121
* - `cli`: Command-line interface mode.
2222
* - `programmatic`: Programmatic interaction mode where the application is used as a library or API.
2323
* - `test`: Testing or debugging mode.
24+
* - `docs`: Documentation mode for building PatternFly documentation.
2425
* @property {ModeOptions} modeOptions - Mode-specific options.
2526
* @property name - Name of the package.
2627
* @property nodeVersion - Node.js major version.
@@ -51,7 +52,7 @@ interface DefaultOptions<TLogOptions = LoggingOptions> {
5152
isHttp: boolean;
5253
logging: TLogOptions;
5354
minMax: MinMax;
54-
mode: 'cli' | 'programmatic' | 'test';
55+
mode: 'cli' | 'programmatic' | 'test' | 'docs';
5556
modeOptions: ModeOptions;
5657
name: string;
5758
nodeVersion: number;
@@ -170,6 +171,7 @@ interface ModeOptions {
170171
test?: {
171172
baseUrl?: string | undefined;
172173
} | undefined;
174+
docs?: object | undefined;
173175
}
174176

175177
/**
@@ -205,6 +207,13 @@ interface PatternFlyOptions {
205207
versionWhitelist: string[];
206208
versionStrategy: 'highest' | 'lowest';
207209
},
210+
api: {
211+
expireDays: number;
212+
endpoints: {
213+
v6: WhitelistUrl;
214+
v5?: WhitelistUrl;
215+
}
216+
},
208217
urlWhitelist: WhitelistUrl[];
209218
urlWhitelistProtocols: string[];
210219
}
@@ -348,7 +357,8 @@ const MIN_MAX: MinMax = {
348357
const MODE_OPTIONS: ModeOptions = {
349358
cli: {},
350359
programmatic: {},
351-
test: {}
360+
test: {},
361+
docs: {}
352362
};
353363

354364
/**
@@ -455,8 +465,15 @@ const PATTERNFLY_OPTIONS: PatternFlyOptions = {
455465
],
456466
versionStrategy: 'highest'
457467
},
468+
api: {
469+
expireDays: 14,
470+
endpoints: {
471+
v6: 'https://patternfly-doc-core.pages.dev/api/v6'
472+
}
473+
},
458474
urlWhitelist: [
459475
'https://patternfly.org',
476+
'https://patternfly-doc-core.pages.dev',
460477
'https://github.com/patternfly',
461478
'https://raw.githubusercontent.com/patternfly'
462479
],
@@ -471,7 +488,7 @@ const URL_REGEX = /^(https?:)\/\//i;
471488
/**
472489
* Available operational modes for the MCP server.
473490
*/
474-
const MODE_LEVELS: DefaultOptions['mode'][] = ['cli', 'programmatic', 'test'];
491+
const MODE_LEVELS: DefaultOptions['mode'][] = ['cli', 'programmatic', 'test', 'docs'];
475492

476493
/**
477494
* Get the current Node.js major version.

0 commit comments

Comments
 (0)