@slbdn/mcp-tester 1.5.4 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -42,7 +42,7 @@ const client = new MCPClient({
42
42
 
43
43
  ### `start(config: ServerConfig): Promise<void>`
44
44
 
45
- Start the client and connect to an MCP server. Supports three transport types:
45
+ Start the client and connect to an MCP server. Supports four transport types:
46
46
 
47
47
  #### Stdio (default)
48
48
 
@@ -99,6 +99,23 @@ await client.start({
99
99
  });
100
100
  ```
101
101
 
102
+ #### WebSocket
103
+
104
+ Connects to a server over WebSocket using the browser-native `WebSocket` API
105
+ and the `mcp` subprotocol. Browser-friendly.
106
+
107
+ | Param | Type | Required | Description |
108
+ |-------|------|----------|-------------|
109
+ | `config.transport` | `'websocket'` | ✅ | Must be `'websocket'` |
110
+ | `config.url` | `string` | ✅ | `ws://` or `wss://` server URL |
111
+
112
+ ```typescript
113
+ await client.start({
114
+ transport: 'websocket',
115
+ url: 'wss://api.example.com/mcp',
116
+ });
117
+ ```
118
+
102
119
  **Throws:**
103
120
  - `MCPAlreadyStartedError` — if the client is already connected
104
121
  - `MCPConnectionError` — if the connection fails
@@ -127,7 +144,7 @@ if (client.isConnected()) {
127
144
 
128
145
  ### `getTransportType(): TransportType | null`
129
146
 
130
- Get the active transport type. Returns `'stdio'`, `'http'`, `'sse'`, or `null`.
147
+ Get the active transport type. Returns `'stdio'`, `'http'`, `'sse'`, `'websocket'`, or `null`.
131
148
 
132
149
  ```typescript
133
150
  const type = client.getTransportType();
@@ -553,17 +570,67 @@ All matchers support `.not` negation and work identically in Jest and Vitest.
553
570
 
554
571
  ## Types
555
572
 
556
- ### MCPServerConfig
573
+ ### ServerConfig
574
+
575
+ Union of every transport configuration accepted by `start()`:
576
+
577
+ ```typescript
578
+ type ServerConfig =
579
+ | StdioServerConfig
580
+ | StreamableHttpServerConfig
581
+ | SseServerConfig
582
+ | WebSocketServerConfig;
583
+
584
+ type TransportType = 'stdio' | 'http' | 'sse' | 'websocket';
585
+ ```
586
+
587
+ ### StdioServerConfig (default)
557
588
 
558
589
  ```typescript
559
- interface MCPServerConfig {
590
+ interface StdioServerConfig {
591
+ transport?: 'stdio';
560
592
  command: string;
561
593
  args?: string[];
562
594
  env?: Record<string, string | undefined>;
563
- startupDelay?: number;
595
+ startupDelay?: number; // default 0
564
596
  }
565
597
  ```
566
598
 
599
+ ### StreamableHttpServerConfig
600
+
601
+ ```typescript
602
+ interface StreamableHttpServerConfig {
603
+ transport: 'http';
604
+ url: string;
605
+ headers?: Record<string, string>;
606
+ sessionId?: string;
607
+ requestInit?: RequestInit;
608
+ }
609
+ ```
610
+
611
+ ### SseServerConfig (deprecated)
612
+
613
+ ```typescript
614
+ interface SseServerConfig {
615
+ transport: 'sse';
616
+ url: string;
617
+ headers?: Record<string, string>;
618
+ requestInit?: RequestInit;
619
+ }
620
+ ```
621
+
622
+ ### WebSocketServerConfig
623
+
624
+ ```typescript
625
+ interface WebSocketServerConfig {
626
+ transport: 'websocket';
627
+ url: string; // ws:// or wss://
628
+ }
629
+ ```
630
+
631
+ > `MCPServerConfig` is a deprecated alias for `StdioServerConfig`, kept for
632
+ > backward compatibility.
633
+
567
634
  ### MCPClientOptions
568
635
 
569
636
  ```typescript
@@ -0,0 +1,138 @@
1
+ # Browser Support
2
+
3
+ `mcp-tester` can run inside browser and edge runtimes to test MCP servers over
4
+ network transports. This is useful for:
5
+
6
+ - Component/unit tests that run in a real browser (Vitest browser mode, Karma,
7
+ Playwright component testing, Web Test Runner).
8
+ - In-browser debugging or smoke checks of a remote MCP server.
9
+ - Edge runtimes (Cloudflare Workers, Deno Deploy, Vercel Edge) that expose
10
+ `fetch` and `WebSocket`.
11
+
12
+ ## How it works
13
+
14
+ The package declares a `browser` field in `package.json`:
15
+
16
+ ```json
17
+ "browser": {
18
+ "./dist/index.js": "./dist/browser.js",
19
+ "./dist/utils/stdio-transport.js": false
20
+ }
21
+ ```
22
+
23
+ When a bundler targets the browser it resolves the package entry to
24
+ `dist/browser.js` and replaces the Node-only stdio transport with an empty
25
+ module. You import the package exactly as you would on Node:
26
+
27
+ ```typescript
28
+ import { MCPClient, assert } from '@slbdn/mcp-tester';
29
+
30
+ const client = new MCPClient();
31
+ await client.start({ transport: 'http', url: 'https://api.example.com/mcp' });
32
+
33
+ const result = await client.callTool({ name: 'echo', arguments: { message: 'hi' } });
34
+ assert.toolTextContains(result, 'hi');
35
+
36
+ await client.stop();
37
+ ```
38
+
39
+ Webpack, Vite, Rollup, esbuild, Parcel, and Rspack all honor the `browser`
40
+ field. The repository's CI runs `npm run test:browser`, which bundles the
41
+ package with esbuild using `platform: 'browser'` and fails if any Node built-in
42
+ (`node:*`) or the stdio transport (`cross-spawn`) leaks into the bundle.
43
+
44
+ ## Transports
45
+
46
+ | Transport | Browser | Notes |
47
+ |-----------|:-------:|-------|
48
+ | `http` (Streamable HTTP) | ✅ | Uses `fetch` + `ReadableStream`. Recommended for remote servers. |
49
+ | `sse` (legacy) | ✅ | Uses `fetch` + `EventSource` semantics. |
50
+ | `websocket` | ✅ | Uses the global `WebSocket` API. |
51
+ | `stdio` | ❌ | Spawns a local process; Node.js only. |
52
+
53
+ ### Streamable HTTP
54
+
55
+ ```typescript
56
+ await client.start({
57
+ transport: 'http',
58
+ url: 'https://api.example.com/mcp',
59
+ headers: { Authorization: 'Bearer token' },
60
+ });
61
+ ```
62
+
63
+ ### WebSocket
64
+
65
+ ```typescript
66
+ await client.start({
67
+ transport: 'websocket',
68
+ url: 'wss://api.example.com/mcp',
69
+ });
70
+ ```
71
+
72
+ The client connects using the `mcp` WebSocket subprotocol, matching the MCP
73
+ SDK's `WebSocketClientTransport`.
74
+
75
+ > **Node.js note:** the WebSocket transport needs a global `WebSocket`.
76
+ > Node.js 22+ provides one. On older Node versions use `--experimental-websocket`
77
+ > or a polyfill such as [`ws`](https://www.npmjs.com/package/ws) installed on
78
+ > `globalThis`.
79
+
80
+ ## What is included
81
+
82
+ The browser entry point (`dist/browser.js`) exports the browser-safe subset:
83
+
84
+ - `MCPClient` and all client types (`ServerConfig`, `StreamableHttpServerConfig`,
85
+ `SseServerConfig`, `WebSocketServerConfig`, `MCPClientOptions`, `HealthStatus`, …)
86
+ - Custom matchers (`toHaveTool`, `toReturnText`, `setupVitestMatchers`, …)
87
+ - The `assert` module
88
+ - Error classes (`MCPClientError`, `MCPTimeoutError`, …)
89
+ - Logging/masking utilities (`startTimer`, `prettyPrint`, `maskSecrets`, …)
90
+ - The deterministic edge-case generator (`suggestEdgeCases`, `generateToolArgs`, …)
91
+
92
+ ## What is Node-only
93
+
94
+ These are intentionally excluded and tree-shaken from browser bundles:
95
+
96
+ - **stdio transport** — spawns a child process via `cross-spawn`.
97
+ - **`generateTests` / `generateTypes`** — read/write files and read the package
98
+ version from disk.
99
+ - **AI provider** (`OpenAICompatProvider`, `createProviderFromEnv`) — uses
100
+ `node:crypto`, `node:fs`, and `node:path`.
101
+
102
+ If you need test generation in a browser workflow, generate the files in a Node
103
+ step (CLI or script) and run the generated tests in the browser.
104
+
105
+ ## Limitations
106
+
107
+ - **No stdio.** Browsers cannot spawn processes. Use `http`, `sse`, or
108
+ `websocket`.
109
+ - **CORS applies.** The MCP server must send appropriate
110
+ `Access-Control-Allow-Origin` headers (and allow the `mcp-session-id` header
111
+ for Streamable HTTP). This is a browser/network constraint, not a limitation
112
+ of this library.
113
+ - **File-based caching is unavailable.** The AI provider (Node-only) writes a
114
+ cache to disk; in-browser code paths do not touch the filesystem.
115
+ - **`process`-based features degrade gracefully.** Health checks for stdio PIDs
116
+ return `null`, and logging falls back to a non-TTY format.
117
+
118
+ ## Testing from Node
119
+
120
+ You can exercise the browser-safe entry point from Node without a browser. The
121
+ repository's `test:browser` script is a good template; a focused version is:
122
+
123
+ ```js
124
+ import { build } from 'esbuild';
125
+
126
+ await build({
127
+ entryPoints: ['src/entry.ts'],
128
+ bundle: true,
129
+ platform: 'browser',
130
+ format: 'esm',
131
+ outfile: 'out.js',
132
+ });
133
+ ```
134
+
135
+ If the bundle succeeds, no Node built-ins were pulled in.
136
+
137
+ See also: [Starter Templates](./starter-templates.md) and
138
+ [Testing](./testing.md).
package/docs/cicd.md CHANGED
@@ -39,6 +39,9 @@ jobs:
39
39
  - name: Build TypeScript
40
40
  run: npm run build
41
41
 
42
+ - name: Check browser bundle
43
+ run: npm run test:browser
44
+
42
45
  - name: Run tests
43
46
  run: npm test
44
47
 
package/docs/cli.md CHANGED
@@ -10,7 +10,7 @@ npx @slbdn/mcp-tester test node ./server.js
10
10
 
11
11
  ## Transports
12
12
 
13
- The CLI supports three transport types:
13
+ The CLI supports four transport types:
14
14
 
15
15
  ### Stdio (default)
16
16
 
@@ -43,6 +43,19 @@ mcp-tester test --transport http --url https://api.example.com/mcp --headers '{"
43
43
  mcp-tester test --transport sse --url http://localhost:3000/sse
44
44
  ```
45
45
 
46
+ ### WebSocket
47
+
48
+ ```bash
49
+ mcp-tester test --transport websocket --url ws://localhost:3000
50
+ ```
51
+
52
+ A `ws://` or `wss://` URL passed as the first argument is auto-detected as the
53
+ WebSocket transport:
54
+
55
+ ```bash
56
+ mcp-tester test wss://api.example.com/mcp
57
+ ```
58
+
46
59
  ## Commands
47
60
 
48
61
  ### `test` — Test Server Connection
@@ -6,8 +6,8 @@
6
6
  |----------------|--------|-------|
7
7
  | 18.x | ⚠️ Not Supported | ESM limitations — upgrade recommended |
8
8
  | 20.x (LTS) | ✅ Fully Supported | **Recommended** (minimum required version) |
9
- | 21.x | ✅ Fully Supported | Latest stable |
10
- | 22.x+ | ✅ Compatible | Tested, works |
9
+ | 21.x | ⚠️ Not Supported | End-of-life; dropped from the test matrix in 1.5.2 |
10
+ | 22.x+ | ✅ Fully Supported | Latest LTS, tested |
11
11
 
12
12
  ## Requirements
13
13
 
@@ -36,6 +36,20 @@ Targets TypeScript 5.3+ with ES2022 output.
36
36
  - ✅ Linux (Ubuntu, Debian, CentOS, Alpine)
37
37
  - ✅ Windows 10/11 (via WSL or native Node.js)
38
38
 
39
+ ## Browser and Edge Runtimes
40
+
41
+ Modern browsers and edge runtimes (Cloudflare Workers, Deno Deploy, Vercel
42
+ Edge) are supported for the network transports:
43
+
44
+ | Runtime | stdio | http | sse | websocket |
45
+ |---------|:-----:|:----:|:---:|:---------:|
46
+ | Node.js ≥ 20 | ✅ | ✅ | ✅ | ✅ (global `WebSocket` on ≥ 22) |
47
+ | Browsers | ❌ | ✅ | ✅ | ✅ |
48
+ | Edge runtimes | ❌ | ✅ | ✅ | ✅ |
49
+
50
+ Bundlers select the browser entry point automatically via the `browser` field.
51
+ See [Browser Support](./browser.md) for details.
52
+
39
53
  ## CI/CD Version Specification
40
54
 
41
55
  **GitHub Actions:**