Skip to content

Commit a0d7144

Browse files
committed
feat: support http transport
1 parent 53d69b5 commit a0d7144

31 files changed

+2884
-340
lines changed

README.md

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ The Model Context Protocol (MCP) is an open standard that enables AI assistants
1919
## Prerequisites
2020

2121
- Node.js 20.0.0 or higher
22-
- npm (or another Node package manager)
22+
- NPM (or another Node package manager)
2323

2424
## Installation
2525

@@ -63,7 +63,7 @@ These are the most relevant NPM scripts from package.json:
6363
- `build`: Build the TypeScript project (cleans dist, type-checks, bundles)
6464
- `build:clean`: Remove dist
6565
- `build:watch`: Build in watch mode
66-
- `start`: Run the built server (node dist/index.js)
66+
- `start`: Run the built server, CLI (node dist/cli.js)
6767
- `start:dev`: Run with tsx in watch mode (development)
6868
- `test`: Run linting, type-check, and unit tests in src/
6969
- `test:dev`: Jest watch mode for unit tests
@@ -75,7 +75,7 @@ These are the most relevant NPM scripts from package.json:
7575

7676
## Usage
7777

78-
The MCP server communicates over stdio and provides access to PatternFly documentation through the following tools. Both tools accept an argument named `urlList` which must be an array of strings. Each string is either:
78+
The MCP server can communicate over **stdio** (default) or **HTTP** transport. It provides access to PatternFly documentation through the following tools. Both tools accept an argument named `urlList` which must be an array of strings. Each string is either:
7979
- An external URL (e.g., a raw GitHub URL to a .md file), or
8080
- A local file path (e.g., documentation/.../README.md). When running with the --docs-host flag, these paths are resolved under the llms-files directory instead.
8181

@@ -143,6 +143,68 @@ npx @patternfly/patternfly-mcp --docs-host
143143

144144
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.
145145

146+
## HTTP transport mode
147+
148+
By default, the server communicates over stdio. To run the server over HTTP instead, use the `--http` flag. This enables the server to accept HTTP requests on a specified port and host.
149+
150+
### Basic HTTP usage
151+
152+
```bash
153+
npx @patternfly/patternfly-mcp --http
154+
```
155+
156+
This starts the server on `http://127.0.0.1:8080` (default port and host).
157+
158+
### HTTP options
159+
160+
- `--http`: Enable HTTP transport mode (default: stdio)
161+
- `--port <number>`: Port number to listen on (default: 8080)
162+
- `--host <string>`: Host address to bind to (default: 127.0.0.1)
163+
- `--allowed-origins <origins>`: Comma-separated list of allowed CORS origins
164+
- `--allowed-hosts <hosts>`: Comma-separated list of allowed host headers
165+
166+
#### Security note: DNS rebinding protection (default)
167+
168+
This server enables DNS rebinding protection by default when running in HTTP mode. If you're behind a proxy or load balancer, ensure the client sends a correct `Host` header and configure `--allowed-hosts` accordingly. Otherwise, requests may be rejected by design. For example:
169+
170+
```bash
171+
npx @patternfly/patternfly-mcp --http \
172+
--host 0.0.0.0 --port 8080 \
173+
--allowed-hosts "localhost,127.0.0.1,example.com"
174+
```
175+
176+
If your client runs on a different origin, also set `--allowed-origins` to allow CORS. Example:
177+
178+
```bash
179+
npx @patternfly/patternfly-mcp --http \
180+
--allowed-origins "http://localhost:5173,https://app.example.com"
181+
```
182+
183+
### Examples
184+
185+
Start on a custom port:
186+
```bash
187+
npx @patternfly/patternfly-mcp --http --port 8080
188+
```
189+
190+
Start on a specific host:
191+
```bash
192+
npx @patternfly/patternfly-mcp --http --host 0.0.0.0 --port 8080
193+
```
194+
195+
Start with CORS allowed origins:
196+
```bash
197+
npx @patternfly/patternfly-mcp --http --allowed-origins "http://localhost:3001,https://example.com"
198+
```
199+
200+
### Port conflict handling
201+
202+
If the specified port is already in use, the server will:
203+
- Display a helpful error message with the process ID (if available)
204+
- Suggest using a different port with `--port` or stopping the process using the port
205+
206+
**Note**: The server uses memoization to prevent duplicate server instances within the same process. If you need to restart the server, simply stop the existing instance and start a new one.
207+
146208
## MCP client configuration examples
147209

148210
Most MCP clients use a JSON configuration to specify how to start this server. The server itself only reads CLI flags and environment variables, not the JSON configuration. Below are examples you can adapt to your MCP client.
@@ -182,14 +244,49 @@ Most MCP clients use a JSON configuration to specify how to start this server. T
182244
"mcpServers": {
183245
"patternfly-docs": {
184246
"command": "node",
185-
"args": ["dist/index.js"],
247+
"args": ["dist/cli.js"],
186248
"cwd": "/path/to/patternfly-mcp",
187249
"description": "PatternFly docs (local build)"
188250
}
189251
}
190252
}
191253
```
192254

255+
### HTTP transport mode
256+
257+
```json
258+
{
259+
"mcpServers": {
260+
"patternfly-docs": {
261+
"command": "npx",
262+
"args": ["-y", "@patternfly/patternfly-mcp@latest", "--http", "--port", "8080"],
263+
"description": "PatternFly docs (HTTP transport)"
264+
}
265+
}
266+
}
267+
```
268+
269+
### HTTP transport with custom options
270+
271+
```json
272+
{
273+
"mcpServers": {
274+
"patternfly-docs": {
275+
"command": "npx",
276+
"args": [
277+
"-y",
278+
"@patternfly/patternfly-mcp@latest",
279+
"--http",
280+
"--port", "8080",
281+
"--host", "0.0.0.0",
282+
"--allowed-origins", "http://localhost:3001,https://example.com"
283+
],
284+
"description": "PatternFly docs (HTTP transport, custom port/host/CORS)"
285+
}
286+
}
287+
}
288+
```
289+
193290
## Inspector-CLI examples (tools/call)
194291

195292
Note: The parameter name is urlList and it must be a JSON array of strings.
@@ -254,7 +351,9 @@ const serverWithOptions = await start({ docsHost: true });
254351
// Multiple options can be overridden
255352
const customServer = await start({
256353
docsHost: true,
257-
// Future CLI options can be added here
354+
http: true,
355+
port: 8080,
356+
host: '0.0.0.0'
258357
});
259358

260359
// TypeScript users can use the CliOptions type for type safety

jest.setupTests.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@
55
*/
66
process.env.NODE_ENV = 'local';
77

8+
/**
9+
* Note: Mock child_process to avoid issues with execSync in tests
10+
*/
11+
jest.mock('child_process', () => ({
12+
...jest.requireActual('child_process'),
13+
execSync: (...args: any) => `<execSync>${JSON.stringify(args)}</execSync>`
14+
}));
15+
16+
/**
17+
* Note: Mock pid-port to avoid ES module import issues in Jest
18+
* - Returns undefined to simulate port is free (no process found)
19+
*/
20+
jest.mock('pid-port', () => ({
21+
__esModule: true,
22+
portToPid: jest.fn().mockResolvedValue(undefined)
23+
}));
24+
825
/**
926
* Note: Mock @patternfly/patternfly-component-schemas/json to avoid top-level await issues in Jest
1027
* - Individual tests can override mock

0 commit comments

Comments
 (0)