Skip to content
Draft
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ yarn-error.log*
# Build output
dist/
build/
cache/
*.tsbuildinfo

# Environment variables
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"type": "module",
"imports": {
"~docsCatalog": "./src/docs.json",
"#buildDocs": "./dist/patternFly.buildDocs.js",
"#toolsHost": "./dist/server.toolsHost.js"
},
"exports": {
Expand All @@ -27,6 +28,7 @@
"scripts": {
"build": "npm run build:clean; npm run test:types; pkgroll",
"build:clean": "rm -rf dist",
"build:api": "node dist/cli.js --mode docs --log-stderr",
"build:watch": "npm run build -- --watch",
"release": "changelog --non-cc --link-url https://github.com/patternfly/patternfly-mcp.git",
"start": "node dist/cli.js --log-stderr",
Expand Down
8 changes: 8 additions & 0 deletions src/__tests__/__snapshots__/options.defaults.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,19 @@ exports[`options defaults should return specific properties: defaults 1`] = `
"mode": "programmatic",
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
"name": "@patternfly/patternfly-mcp",
"nodeVersion": 22,
"patternflyOptions": {
"api": {
"endpoints": {
"v6": "https://patternfly-doc-core.pages.dev/api/v6",
},
"expireDays": 14,
},
"availableResourceVersions": [
"6.0.0",
],
Expand All @@ -70,6 +77,7 @@ exports[`options defaults should return specific properties: defaults 1`] = `
},
"urlWhitelist": [
"https://patternfly.org",
"https://patternfly-doc-core.pages.dev",
"https://github.com/patternfly",
"https://raw.githubusercontent.com/patternfly",
],
Expand Down
12 changes: 12 additions & 0 deletions src/__tests__/__snapshots__/options.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ exports[`parseCliOptions should attempt to parse args with --allowed-hosts 1`] =
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -44,6 +45,7 @@ exports[`parseCliOptions should attempt to parse args with --allowed-origins 1`]
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -67,6 +69,7 @@ exports[`parseCliOptions should attempt to parse args with --http and --host 1`]
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -90,6 +93,7 @@ exports[`parseCliOptions should attempt to parse args with --http and --port 1`]
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -113,6 +117,7 @@ exports[`parseCliOptions should attempt to parse args with --http and invalid --
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -134,6 +139,7 @@ exports[`parseCliOptions should attempt to parse args with --http flag 1`] = `
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -155,6 +161,7 @@ exports[`parseCliOptions should attempt to parse args with --log-level flag 1`]
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -176,6 +183,7 @@ exports[`parseCliOptions should attempt to parse args with --log-stderr flag and
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -197,6 +205,7 @@ exports[`parseCliOptions should attempt to parse args with --tool 1`] = `
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -221,6 +230,7 @@ exports[`parseCliOptions should attempt to parse args with --verbose flag 1`] =
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -242,6 +252,7 @@ exports[`parseCliOptions should attempt to parse args with --verbose flag and --
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand All @@ -263,6 +274,7 @@ exports[`parseCliOptions should attempt to parse args with other arguments 1`] =
},
"modeOptions": {
"cli": {},
"docs": {},
"programmatic": {},
"test": {},
},
Expand Down
30 changes: 30 additions & 0 deletions src/__tests__/api.json.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import apiJson from '../api.json';

describe('api.json', () => {
it('should have a valid top-level generated timestamp (ISO date string)', () => {
expect(apiJson.generated).toBeDefined();
expect(typeof apiJson.generated).toBe('string');
expect(apiJson.generated.length).toBeGreaterThan(0);

const rawDate = apiJson.generated;
const parsedDate = Date.parse(rawDate);

expect(Number.isNaN(parsedDate)).toBe(false);

// Canonical ISO 8601 UTC form from Date.prototype.toISOString()
expect(new Date(parsedDate).toISOString()).toBe(rawDate);
});

it('should have a valid meta structure', () => {
expect(apiJson.meta).toBeDefined();
expect(apiJson.meta.totalEntries).toBeDefined();
expect(apiJson.meta.totalDocs).toBeDefined();
expect(apiJson.meta.source).toBe('patternfly-mcp-api');
expect(apiJson.meta.lastBuildRun).toBeDefined();
});

it('should have a docs object', () => {
expect(apiJson.docs).toBeDefined();
expect(typeof apiJson.docs).toBe('object');
});
});
11 changes: 11 additions & 0 deletions src/api.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": "1",
"generated": "2026-03-23T20:00:00.000Z",
"meta": {
"totalEntries": 0,
"totalDocs": 0,
"source": "patternfly-mcp-api",
"lastBuildRun": "2026-03-23T20:00:00.000Z"
},
"docs": {}
}
1 change: 1 addition & 0 deletions src/docs.embedded.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ interface PatternFlyMcpDocsCatalog {
totalEntries: number;
totalDocs: number;
source: string;
[key: string]: unknown;
};
docs: PatternFlyMcpDocsCatalogEntry
}
Expand Down
16 changes: 16 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,22 @@

// Finalize exit policy after merging options
updatedAllowProcessExit = allowProcessExit ?? mergedOptions.mode !== 'test';

// Handle documentation building mode
if (mergedOptions.mode === 'docs') {
const { createLogger } = await import('./logger');
const { buildPatternFlyDocs } = await import('#buildDocs' as string);

createLogger();

const instance = await buildPatternFlyDocs(mergedOptions);

if (updatedAllowProcessExit) {
process.exit(0);
}

return instance as any;

Check warning on line 193 in src/index.ts

View workflow job for this annotation

GitHub Actions / Integration-checks (22.x)

Unexpected any. Specify a different type

Check warning on line 193 in src/index.ts

View workflow job for this annotation

GitHub Actions / Integration-checks (24.x)

Unexpected any. Specify a different type

Check warning on line 193 in src/index.ts

View workflow job for this annotation

GitHub Actions / Integration-checks (20.x)

Unexpected any. Specify a different type
}
} catch (error) {
processExit('Set options error, failed to start server:', error);
}
Expand Down
23 changes: 20 additions & 3 deletions src/options.defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { type ToolModule } from './server.toolsUser';
* - `cli`: Command-line interface mode.
* - `programmatic`: Programmatic interaction mode where the application is used as a library or API.
* - `test`: Testing or debugging mode.
* - `docs`: Documentation mode for building PatternFly documentation.
* @property {ModeOptions} modeOptions - Mode-specific options.
* @property name - Name of the package.
* @property nodeVersion - Node.js major version.
Expand Down Expand Up @@ -51,7 +52,7 @@ interface DefaultOptions<TLogOptions = LoggingOptions> {
isHttp: boolean;
logging: TLogOptions;
minMax: MinMax;
mode: 'cli' | 'programmatic' | 'test';
mode: 'cli' | 'programmatic' | 'test' | 'docs';
modeOptions: ModeOptions;
name: string;
nodeVersion: number;
Expand Down Expand Up @@ -170,6 +171,7 @@ interface ModeOptions {
test?: {
baseUrl?: string | undefined;
} | undefined;
docs?: object | undefined;
}

/**
Expand Down Expand Up @@ -205,6 +207,13 @@ interface PatternFlyOptions {
versionWhitelist: string[];
versionStrategy: 'highest' | 'lowest';
},
api: {
expireDays: number;
endpoints: {
v6: WhitelistUrl;
v5?: WhitelistUrl;
}
},
urlWhitelist: WhitelistUrl[];
urlWhitelistProtocols: string[];
}
Expand Down Expand Up @@ -348,7 +357,8 @@ const MIN_MAX: MinMax = {
const MODE_OPTIONS: ModeOptions = {
cli: {},
programmatic: {},
test: {}
test: {},
docs: {}
};

/**
Expand Down Expand Up @@ -455,8 +465,15 @@ const PATTERNFLY_OPTIONS: PatternFlyOptions = {
],
versionStrategy: 'highest'
},
api: {
expireDays: 14,
endpoints: {
v6: 'https://patternfly-doc-core.pages.dev/api/v6'
}
},
urlWhitelist: [
'https://patternfly.org',
'https://patternfly-doc-core.pages.dev',
'https://github.com/patternfly',
'https://raw.githubusercontent.com/patternfly'
],
Expand All @@ -471,7 +488,7 @@ const URL_REGEX = /^(https?:)\/\//i;
/**
* Available operational modes for the MCP server.
*/
const MODE_LEVELS: DefaultOptions['mode'][] = ['cli', 'programmatic', 'test'];
const MODE_LEVELS: DefaultOptions['mode'][] = ['cli', 'programmatic', 'test', 'docs'];

/**
* Get the current Node.js major version.
Expand Down
Loading
Loading