@slbdn/mcp-tester 1.5.3 → 1.6.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.
- package/CHANGELOG.md +19 -0
- package/README.md +93 -41
- package/dist/browser.d.ts +42 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +37 -0
- package/dist/browser.js.map +1 -0
- package/dist/cli/index.js +27 -22
- package/dist/cli/index.js.map +1 -1
- package/dist/client/MCPClient.d.ts +18 -1
- package/dist/client/MCPClient.d.ts.map +1 -1
- package/dist/client/MCPClient.js +30 -6
- package/dist/client/MCPClient.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +2 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/stdio-transport.d.ts +18 -0
- package/dist/utils/stdio-transport.d.ts.map +1 -0
- package/dist/utils/stdio-transport.js +18 -0
- package/dist/utils/stdio-transport.js.map +1 -0
- package/dist/utils/validation.d.ts +3 -2
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +27 -14
- package/dist/utils/validation.js.map +1 -1
- package/docs/api-reference.md +72 -5
- package/docs/browser.md +138 -0
- package/docs/cicd.md +3 -0
- package/docs/cli.md +14 -1
- package/docs/nodejs-compatibility.md +16 -2
- package/docs/testing.md +3 -0
- package/docs/troubleshooting.md +23 -2
- package/package.json +7 -1
package/docs/api-reference.md
CHANGED
|
@@ -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
|
|
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
|
-
###
|
|
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
|
|
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
|
package/docs/browser.md
ADDED
|
@@ -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
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
|
|
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 |
|
|
10
|
-
| 22.x+ | ✅
|
|
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:**
|
package/docs/testing.md
CHANGED
|
@@ -8,6 +8,7 @@ Guide to writing and running tests with MCP Tester.
|
|
|
8
8
|
npm test # Run all tests
|
|
9
9
|
npm run test:watch # Watch mode (auto-rerun on changes)
|
|
10
10
|
npm run test:coverage # Run with coverage report
|
|
11
|
+
npm run test:browser # Bundle-check the browser build (esbuild)
|
|
11
12
|
npm run lint # Lint code
|
|
12
13
|
```
|
|
13
14
|
|
|
@@ -20,6 +21,8 @@ src/__tests__/
|
|
|
20
21
|
├── advanced.test.ts # Sampling, elicitation
|
|
21
22
|
├── real-server.test.ts # Integration tests (stdio transport)
|
|
22
23
|
├── everything-server.test.ts # Full integration (server-everything)
|
|
24
|
+
├── http-transport.test.ts # Streamable HTTP / SSE transport
|
|
25
|
+
├── websocket-transport.test.ts # WebSocket transport (in-process double)
|
|
23
26
|
├── cli.test.ts # CLI tool tests
|
|
24
27
|
└── fixtures/
|
|
25
28
|
└── mock-server.ts # In-memory mock MCP server
|
package/docs/troubleshooting.md
CHANGED
|
@@ -114,8 +114,8 @@ Coverage thresholds: **80%** for branches, functions, lines, and statements.
|
|
|
114
114
|
|
|
115
115
|
## Known Limitations
|
|
116
116
|
|
|
117
|
-
- Supports **stdio**, **Streamable HTTP**, and **
|
|
118
|
-
-
|
|
117
|
+
- Supports **stdio**, **Streamable HTTP**, **SSE**, and **WebSocket** transports
|
|
118
|
+
- Node.js by default; the HTTP/SSE/WebSocket transports also run in browsers and edge runtimes (see [Browser Support](./browser.md))
|
|
119
119
|
- Mock server has configurable delays, failures, stateful tools, and validation
|
|
120
120
|
|
|
121
121
|
## Vitest
|
|
@@ -137,3 +137,24 @@ If you get TypeScript errors with custom matchers, make sure your `tsconfig.json
|
|
|
137
137
|
"include": ["node_modules/@slbdn/mcp-tester/vitest.d.ts"]
|
|
138
138
|
}
|
|
139
139
|
```
|
|
140
|
+
|
|
141
|
+
## Browser and Edge Runtimes
|
|
142
|
+
|
|
143
|
+
**"Module not found: node:child_process" / "cross-spawn" in a browser build**
|
|
144
|
+
Your bundler is not honouring the `browser` field. Ensure it targets `browser`
|
|
145
|
+
(Webpack `target: 'web'`, Vite `build.target` not `ssr`, esbuild
|
|
146
|
+
`platform: 'browser'`). The repo's `npm run test:browser` script is a minimal
|
|
147
|
+
reference. Do not import `@slbdn/mcp-tester/dist/...` deep paths — import the
|
|
148
|
+
package root so the browser entry point is selected.
|
|
149
|
+
|
|
150
|
+
**"WebSocket is not defined" (Node.js)**
|
|
151
|
+
The WebSocket transport needs a global `WebSocket`. Node.js 22+ provides one;
|
|
152
|
+
on older versions enable it with `--experimental-websocket` or set a polyfill
|
|
153
|
+
such as `ws` on `globalThis`.
|
|
154
|
+
|
|
155
|
+
**CORS errors against a remote MCP server**
|
|
156
|
+
The server must allow your origin and, for Streamable HTTP, the
|
|
157
|
+
`mcp-session-id` header. This is a browser/network constraint — configure the
|
|
158
|
+
server, not the client.
|
|
159
|
+
|
|
160
|
+
See [Browser Support](./browser.md) for the full matrix.
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slbdn/mcp-tester",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "Minimal MCP client implementation for CI/CD testing of MCP servers",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
|
+
"browser": {
|
|
7
|
+
"./dist/index.js": "./dist/browser.js",
|
|
8
|
+
"./dist/utils/stdio-transport.js": false
|
|
9
|
+
},
|
|
6
10
|
"types": "dist/index.d.ts",
|
|
7
11
|
"type": "module",
|
|
8
12
|
"sideEffects": false,
|
|
@@ -24,6 +28,7 @@
|
|
|
24
28
|
"test:watch": "jest --watch",
|
|
25
29
|
"test:coverage": "jest --coverage",
|
|
26
30
|
"test:package": "node scripts/smoke-test-package.mjs",
|
|
31
|
+
"test:browser": "node scripts/check-browser-bundle.mjs",
|
|
27
32
|
"benchmark": "tsx src/__tests__/benchmarks.ts",
|
|
28
33
|
"lint": "eslint src --ext .ts",
|
|
29
34
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
@@ -77,6 +82,7 @@
|
|
|
77
82
|
"@types/node": "^20.19.41",
|
|
78
83
|
"@typescript-eslint/eslint-plugin": "^8.60.0",
|
|
79
84
|
"@typescript-eslint/parser": "^8.60.0",
|
|
85
|
+
"esbuild": "^0.28.2",
|
|
80
86
|
"eslint": "^8.56.0",
|
|
81
87
|
"fast-check": "^4.8.0",
|
|
82
88
|
"husky": "^9.1.7",
|