Complete guide to using the PatternFly MCP Server for development including CLI and programmatic API usage.
Development:
| Flag | Description | Default |
|---|---|---|
--http |
Enable HTTP transport mode | false (stdio mode) |
--port <num> |
Port for HTTP transport | 8080 |
--host <string> |
Host to bind to | 127.0.0.1 |
--allowed-origins <origins> |
Comma-separated list of allowed CORS origins | none |
--allowed-hosts <hosts> |
Comma-separated list of allowed host headers | none |
--tool <path> |
Path to external Tool Plugin (repeatable) | none |
--plugin-isolation <none | strict> |
Isolation preset for external tools-as-plugins | strict |
--log-stderr |
Enable terminal logging | false |
--log-protocol |
Forward logs to MCP clients | false |
--log-level <level> |
Set log level (debug, info, warn, error) |
info |
--mode <mode> |
Operational mode (cli, programmatic, test) |
cli |
--mode-test-url <url> |
Base URL for fixture/mock servers in test mode |
none |
--verbose |
Shortcut for --log-level debug |
false |
- HTTP transport mode - By default, the server uses
stdio. Use the--httpflag to enable HTTP transport. - Logging - The server uses a
diagnostics_channel-based logger that keeps STDIO stdout pure by default. - Programmatic API - The server can also be used programmatically with options. See Programmatic Usage for more details.
- Tool Plugins - The server can load external tool plugins at startup. See Tool Plugins for more details.
- Test Mode - When
--mode testis used, the server redirects resource requests to the URL provided by--mode-test-url, enabling E2E testing without local filesystem access.
stdio mode (default):
npx @patternfly/patternfly-mcpHTTP mode:
npx @patternfly/patternfly-mcp --http --port 8080HTTP mode with custom security:
npx @patternfly/patternfly-mcp --http --port 3000 --allowed-origins "https://app.com"Loading external tool plugins:
npx @patternfly/patternfly-mcp --tool ./first-tool.js --tool ./second-tool.tsTesting with a fixture server:
npx @patternfly/patternfly-mcp --mode test --mode-test-url "http://localhost:3000"The @modelcontextprotocol/inspector is the recommended way to visualize the server's interface.
- Start the Inspector:
npx -y @modelcontextprotocol/inspector npx @patternfly/patternfly-mcp
- Interact: The inspector opens a web interface (typically at
http://localhost:5173) where you can list tools, execute them, and view resource contents.
Example with repository context:
npx @modelcontextprotocol/inspector-cli \
--config ./mcp-config.json \
--server patternfly-docs \
--cli \
--method tools/call \
--tool-name usePatternFlyDocs \
--tool-arg name="Button"The start() function accepts an optional PfMcpOptions object for programmatic configuration. Use these options to customize behavior, transport, and logging for embedded instances.
| Option | Type | Description | Default |
|---|---|---|---|
toolModules |
ToolModule | ToolModule[] |
Array of tool modules or paths to external tool plugins to be loaded. | [] |
isHttp |
boolean |
Enable HTTP transport mode. | false |
http.port |
number |
Port for HTTP transport. | 8080 |
http.host |
string |
Host to bind to. | 127.0.0.1 |
http.allowedOrigins |
string[] |
List of allowed CORS origins. | [] |
http.allowedHosts |
string[] |
List of allowed host headers. | [] |
pluginIsolation |
'none' | 'strict' |
Isolation preset for external tools-as-plugins. | 'strict' |
logging.level |
'debug' | 'info' | 'warn' | 'error' |
Set the logging level. | 'info' |
logging.stderr |
boolean |
Enable terminal logging to stderr. | false |
logging.protocol |
boolean |
Forward logs to MCP clients. | false |
mode |
'cli' | 'programmatic' | 'test' |
Specifies the operation mode. | 'programmatic' |
modeOptions.test.baseUrl |
string |
Base URL for fixture/mock servers in test mode. |
undefined |
docsPaths |
string[] |
Whitelist of local documentation directories resolved by documentation: slug. When empty (default), the slug is dormant. |
[] |
import { start, type PfMcpInstance, type PfMcpOptions } from '@patternfly/patternfly-mcp';
const options: PfMcpOptions = {
isHttp: true,
http: {
port: 3000,
allowedOrigins: ['https://your-app.com']
},
logging: {
level: 'debug',
stderr: true
}
};
const server: PfMcpInstance = await start(options);The documentation catalog src/docs.json pins remote resources to specific commit SHAs (or explicit refs) for stability and reproducibility. This avoids unexpected upstream changes from breaking results. The searchPatternFlyDocs tool handles these lookups transparently for the user.
Example: Programmatic test mode
import { start, type PfMcpInstance } from '@patternfly/patternfly-mcp';
const server: PfMcpInstance = await start({
mode: 'test',
modeOptions: {
test: {
baseUrl: 'http://my-fixture-server:3000'
}
}
});The server instance exposes the following methods:
isRunning()- Returns aboolean,trueif the server is running.onLog(callback)- Registers a callback for server logs, returns aPfMcpLogEventobject.stop()- Stops the server.getStats()- Returns aPfMcpStatsobject containing server metrics and diagnostic channel IDs.
Checks if the server is running, returns a boolean, true if the server is running.
import { start, type PfMcpInstance } from '@patternfly/patternfly-mcp';
const server: PfMcpInstance = await start({ /* options */ });
if (server.isRunning()) {
// Server is running
}Registers a callback for server logs. The callback receives a PfMcpLogEvent object.
import { start, type PfMcpInstance, type PfMcpLogEvent } from '@patternfly/patternfly-mcp';
const server: PfMcpInstance = await start({ /* options */ });
server.onLog((event: PfMcpLogEvent) => {
if (event.level !== 'debug') {
console.warn(`[${event.level}] ${event.msg || ''}`);
}
});Stops the server.
import { start, type PfMcpInstance } from '@patternfly/patternfly-mcp';
const server: PfMcpInstance = await start({ /* options */ });
process.on('SIGINT', async () => {
await server.stop();
process.exit(0);
});Returns a PfMcpStats object containing server metrics, includes diagnostic channel IDs for listening to server activity.
import { channel, unsubscribe, subscribe } from 'node:diagnostics_channel';
import { start, type PfMcpInstance, type PfMcpStats, type PfMcpStatReport } from '@patternfly/patternfly-mcp';
const server: PfMcpInstance = await start({ /* options */ });
const stats: PfMcpStats = server.getStats();
const logChannel = channel(stats.health.channelId);
const logHandler = (event: PfMcpStatReport) => {
/* Handle log events, on MCP server close unsubscribe */
};
const logSubscription = subscribe(logChannel, logHandler);Reference typings are exported from the package. The full listing can be found in src/index.ts.
You can embed the MCP server inside your application using the start() function and provide Tool Modules directly.
import { start, createMcpTool, type PfMcpInstance, type ToolModule } from '@patternfly/patternfly-mcp';
const echoTool: ToolModule = createMcpTool({
name: 'echoAMessage',
description: 'Echo back the provided user message.',
inputSchema: {
type: 'object',
properties: { message: { type: 'string' } },
required: ['message']
},
handler: async (args: { message: string }) => ({
content: [{ type: 'text', text: `You said: ${args.message}` }]
})
});
const main = async () => {
const server: PfMcpInstance = await start({
toolModules: [
echoTool
]
});
// Optional: observe refined server logs in‑process.
// We recommend getting in the habit of avoiding use of console.log and info, they pollute STDOUT.
server.onLog((event) => {
if (event.level !== 'debug') {
console.warn(`[${event.level}] ${event.msg || ''}`);
}
});
// Graceful shutdown
process.on('SIGINT', async () => {
await server.stop();
process.exit(0);
});
}
main();See examples/ for more programmatic usage examples.
You can extend the server's capabilities by loading Tool Plugins at startup. These plugins run out‑of‑process in an isolated Tools Host to ensure security and stability.
- Node.js >= 22: Loading external tool plugins (
--tool) requires Node.js version 22 or higher due to the use of advanced process isolation and ESM module loading features. - ESM: Plugins MUST be authored as ECMAScript Modules.
- Dependency Resolution: Plugins importing from
@patternfly/patternfly-mcprequire the package to be resolvable in the execution environment. This may require a localnpm installin the plugin's directory or project root if the package is not available globally.
The server provides two isolation modes for external plugins via the --plugin-isolation flag:
strict(Default): The plugin runs in a restricted environment with limited access to the system. This is the recommended mode for most tools.none: The plugin has full access to the system environment, including the filesystem and network, inherited from the host process. Use this mode ONLY if your tool requires specific system access (e.g., executing Git commands or accessing local files outside the sandbox) and you trust the plugin code.
Warning: Disabling isolation (
--plugin-isolation none) increases the security risk. Always document the reason for requiring this mode in your tool's documentation.
Tool: The low-level tuple format[name, schema, handler].Tool Config: The authoring object format{ name, description, inputSchema, handler }.Tool Factory: A function wrapper(options) => Tool(internal).Tool Module: The programmatic result ofcreateMcpTool, representing a collection of tools.
We recommend using the createMcpTool helper to define tools. It ensures your tools are properly normalized for the server.
import { createMcpTool } from '@patternfly/patternfly-mcp';
export default createMcpTool({
name: 'hello',
description: 'Say hello',
inputSchema: {
type: 'object',
properties: { name: { type: 'string' } },
required: ['name']
},
async handler({ name }) {
return {
content: [{ type: 'text', text: `Hello, ${name}!` }]
};
}
});import { createMcpTool } from '@patternfly/patternfly-mcp';
export default createMcpTool([
{ name: 'hi', description: 'Greets', inputSchema: {}, handler: () => ({ content: [{ type: 'text', text: 'hi' }] }) },
{ name: 'bye', description: 'Farewell', inputSchema: {}, handler: () => ({ content: [{ type: 'text', text: 'bye' }] }) }
]);The inputSchema property accepts either plain JSON Schema objects or Zod schemas. Both formats are automatically converted to the format required by the MCP SDK.
JSON Schema (recommended):
const inputSchema = {
type: 'object',
properties: {
name: { type: 'string' },
age: { type: 'number' }
},
required: ['name']
};Zod Schema:
import { z } from 'zod';
const inputSchema = z.object({
name: z.string(),
age: z.number().optional()
});See examples/toolPluginHelloWorld.js for a basic example.
- Plugins don't appear: Verify the Node version (requires Node.js >= 20; >= 22 for tool plugins) and check logs (enable
--log-stderr). - Startup warnings/errors: Startup
load:ackwarnings/errors from tool plugins are logged when stderr/protocol logging is enabled. - Schema errors: If
tools/callrejects with schema errors, ensureinputSchemais valid. See Authoring Tools for details. - Network access issues: If the tool is having network access issues, you may need to configure
--plugin-isolation none. This is generally discouraged for security reasons but may be necessary in some cases.
- Connection issues: Ensure the port is not already in use and the host is correct.
- CORS errors: Configure
--allowed-originsif accessing from a web client. - DNS rebinding protection: If behind a proxy, ensure correct
Hostheader and configure--allowed-hosts.
- Server won't start: Check Node.js version (requires Node.js >= 20; >= 22 for tool plugins).
- Missing tools/resources: Verify the server started successfully and check logs with
--log-stderr. - Type errors: Ensure TypeScript types are installed:
npm install --save-dev @types/node