mock-mcp 0.3.1 → 0.5.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.
Files changed (44) hide show
  1. package/README.md +212 -124
  2. package/dist/adapter/index.cjs +712 -0
  3. package/dist/adapter/index.d.cts +55 -0
  4. package/dist/adapter/index.d.ts +55 -0
  5. package/dist/adapter/index.js +672 -0
  6. package/dist/client/connect.cjs +913 -0
  7. package/dist/client/connect.d.cts +211 -0
  8. package/dist/client/connect.d.ts +204 -7
  9. package/dist/client/connect.js +863 -20
  10. package/dist/client/index.cjs +914 -0
  11. package/dist/client/index.d.cts +4 -0
  12. package/dist/client/index.d.ts +4 -2
  13. package/dist/client/index.js +873 -2
  14. package/dist/daemon/index.cjs +667 -0
  15. package/dist/daemon/index.d.cts +62 -0
  16. package/dist/daemon/index.d.ts +62 -0
  17. package/dist/daemon/index.js +628 -0
  18. package/dist/discovery-Dc2LdF8q.d.cts +105 -0
  19. package/dist/discovery-Dc2LdF8q.d.ts +105 -0
  20. package/dist/index.cjs +2238 -0
  21. package/dist/index.d.cts +472 -0
  22. package/dist/index.d.ts +472 -11
  23. package/dist/index.js +2185 -53
  24. package/dist/protocol-CiwaQFOt.d.ts +239 -0
  25. package/dist/protocol-xZu-wb0n.d.cts +239 -0
  26. package/dist/shared/index.cjs +386 -0
  27. package/dist/shared/index.d.cts +4 -0
  28. package/dist/shared/index.d.ts +4 -0
  29. package/dist/shared/index.js +310 -0
  30. package/dist/types-BKREdsyr.d.cts +32 -0
  31. package/dist/types-BKREdsyr.d.ts +32 -0
  32. package/package.json +44 -4
  33. package/dist/client/batch-mock-collector.d.ts +0 -111
  34. package/dist/client/batch-mock-collector.js +0 -308
  35. package/dist/client/util.d.ts +0 -1
  36. package/dist/client/util.js +0 -3
  37. package/dist/connect.cjs +0 -400
  38. package/dist/connect.d.cts +0 -82
  39. package/dist/server/index.d.ts +0 -1
  40. package/dist/server/index.js +0 -1
  41. package/dist/server/test-mock-mcp-server.d.ts +0 -73
  42. package/dist/server/test-mock-mcp-server.js +0 -419
  43. package/dist/types.d.ts +0 -45
  44. package/dist/types.js +0 -2
package/README.md CHANGED
@@ -4,17 +4,19 @@
4
4
  [![npm](https://img.shields.io/npm/v/mock-mcp.svg)](https://www.npmjs.com/package/mock-mcp)
5
5
  ![license](https://img.shields.io/npm/l/mock-mcp)
6
6
 
7
- Mock MCP Server - AI-generated mock data based on your **OpenAPI JSON Schema** definitions. The project pairs a WebSocket batch bridge with MCP tooling so Cursor, Claude Desktop, or any compatible client can fulfill intercepted requests in real time, ensuring strict contract compliance.
7
+ Mock MCP Server - AI-generated mock data based on your **OpenAPI JSON Schema** definitions. The project uses a **Daemon + Adapter** architecture that enables multiple MCP clients (Cursor, Claude Desktop, etc.) to run simultaneously without port conflicts, while providing robust claim-based concurrency control for mock batch processing.
8
8
 
9
9
  ## Table of Contents
10
10
 
11
11
  - [Quick Start](#quick-start)
12
12
  - [Why Mock MCP](#why-mock-mcp)
13
13
  - [What Mock MCP Does](#what-mock-mcp-does)
14
+ - [Architecture](#architecture)
14
15
  - [Configure MCP Server](#configure-mcp-server)
15
16
  - [Connect From Tests](#connect-from-tests)
16
17
  - [Describe Requests with Metadata](#describe-requests-with-metadata)
17
- - [MCP tools](#mcp-tools)
18
+ - [MCP Tools](#mcp-tools)
19
+ - [CLI Commands](#cli-commands)
18
20
  - [Available APIs](#available-apis)
19
21
  - [Environment Variables](#environment-variables)
20
22
  - [How It Works](#how-it-works)
@@ -33,17 +35,21 @@ yarn add -D mock-mcp
33
35
  pnpm add -D mock-mcp
34
36
  ```
35
37
 
36
- 2. **Configure the Model Context Protocol server.** For example, Claude Desktop can launch the binary through npx:
38
+ 2. **Configure the Model Context Protocol server.** Add mock-mcp to your MCP client configuration (Cursor, Claude Desktop, etc.):
37
39
 
38
40
  ```json
39
41
  {
40
- "mock-mcp": {
41
- "command": "npx",
42
- "args": ["-y", "mock-mcp@latest"]
42
+ "mcpServers": {
43
+ "mock-mcp": {
44
+ "command": "npx",
45
+ "args": ["-y", "mock-mcp", "adapter"]
46
+ }
43
47
  }
44
48
  }
45
49
  ```
46
50
 
51
+ > **Note:** The `adapter` command connects to a shared daemon process that is automatically started when needed. This eliminates port conflicts when running multiple MCP clients simultaneously.
52
+
47
53
  3. **Connect from your tests.** Use `connect` to retrieve a mock client and request data for intercepted calls.
48
54
 
49
55
  ```ts
@@ -132,53 +138,75 @@ Unlike "hallucinated" mocks, Mock MCP uses your actual **OpenAPI JSON Schema** d
132
138
 
133
139
  ## What Mock MCP Does
134
140
 
135
- Mock MCP pairs a WebSocket batch bridge with MCP tooling to move intercepted requests from tests to AI helpers and back again.
141
+ Mock MCP uses a **Daemon + Adapter** architecture to move intercepted requests from tests to AI helpers and back again.
136
142
 
137
143
  - **Schema-aware generation** uses your provided metadata (OpenAPI JSON Schema) to ensure mocks match production behavior.
138
144
  - **Batch-aware test client** collects every network interception inside a single macrotask and waits for the full response set.
139
- - **MCP tooling** exposes `get_pending_batches` and `provide_batch_mock_data` so AI agents understand the waiting requests and push data back.
140
- - **WebSocket bridge** connects the test runner to the MCP server while hiding transport details from both sides.
145
+ - **Claim-based concurrency** prevents multiple AI clients from racing on the same batch through lease-based locking.
146
+ - **Multi-run isolation** supports concurrent test processes with distinct run IDs.
147
+ - **IPC-based communication** uses Unix Domain Sockets (macOS/Linux) or Named Pipes (Windows) instead of TCP ports, eliminating port conflicts.
141
148
  - **Timeouts, TTLs, and cleanup** guard the test runner from stale batches or disconnected clients.
142
149
 
143
- ## Configure MCP Server
150
+ ## Architecture
151
+
152
+ The v0.4.0 release introduces a new **Daemon + Adapter** architecture that fundamentally solves the "multiple MCP clients" problem:
153
+
154
+ ```
155
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
156
+ │ Test Process │ │ Daemon │ │ Adapter │
157
+ │ (your tests) │────▶│ (per-project) │◀────│ (per MCP client)│
158
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
159
+ │ │ │
160
+ │ WebSocket/IPC │ JSON-RPC/IPC │ MCP stdio
161
+ │ │ │
162
+ ▼ ▼ ▼
163
+ BatchMockCollector Mock Bridge Daemon MCP Tools
164
+ - Auto-discovers - Manages runs/batches - claim_next_batch
165
+ - Sends batches - Claim/lease control - provide_batch_mock_data
166
+ - Receives mocks - Multi-client safe - get_status, list_runs
167
+ ```
144
168
 
145
- CLI flags keep the WebSocket bridge and the MCP transports aligned. Use them to adapt the server to your local ports while the Environment Variables section covers per-process overrides:
169
+ **Key Benefits:**
146
170
 
147
- | Option | Description | Default |
148
- | -------------- | ------------------------------------------------------------------ | ------- |
149
- | `--port`, `-p` | WebSocket port for test runners | `3002` |
150
- | `--no-stdio` | Disable the MCP stdio transport (useful for local debugging/tests) | enabled |
171
+ - Single daemon per project (no per-client server instances)
172
+ - IPC communication
173
+ - Full multi-client support
174
+ - Claim-based concurrency (no race conditions)
175
+ - Auto-discovery (no manual configuration)
151
176
 
152
- The CLI installs a SIGINT/SIGTERM handler so `Ctrl+C` shuts everything down cleanly.
177
+ ## Configure MCP Server
153
178
 
154
- **Add the server to MCP clients.** MCP clients such as Cursor or Claude Desktop need an entry in their configuration so they can launch the bridge:
179
+ Add mock-mcp to your MCP client configuration. The adapter automatically discovers or starts the daemon for your project:
155
180
 
156
181
  ```json
157
182
  {
158
183
  "mcpServers": {
159
184
  "mock-mcp": {
160
185
  "command": "npx",
161
- "args": ["-y", "mock-mcp@latest"],
162
- "env": {
163
- "MCP_SERVER_PORT": "3002" // 3002 is the default port
164
- }
186
+ "args": ["-y", "mock-mcp", "adapter"]
165
187
  }
166
188
  }
167
189
  }
168
190
  ```
169
191
 
170
- Restart the client and confirm that the `mock-mcp` server exposes two tools.
192
+ **That's it!** The daemon uses IPC (Unix Domain Sockets on macOS/Linux, Named Pipes on Windows) which:
193
+
194
+ - Eliminates port conflicts between multiple MCP clients
195
+ - Automatically shares state between all adapters in the same project
196
+ - Requires no manual coordination or environment variables
197
+
198
+ Restart your MCP client and confirm that the `mock-mcp` server exposes the tools (`get_status`, `claim_next_batch`, `provide_batch_mock_data`, etc.).
171
199
 
172
200
  ## Connect From Tests
173
201
 
174
- Tests call `connect` to spin up a `BatchMockCollector`, intercept HTTP calls, and wait for fulfilled data:
202
+ Tests call `connect` to spin up a `BatchMockCollector` that automatically discovers and connects to the daemon:
175
203
 
176
204
  ```ts
177
205
  // tests/mocks.ts
178
206
  import { connect } from "mock-mcp";
179
207
 
208
+ // Auto-discovers daemon via IPC
180
209
  const mockClient = await connect({
181
- port: 3002,
182
210
  timeout: 60000,
183
211
  });
184
212
 
@@ -207,6 +235,8 @@ await mockClient.waitForPendingRequests();
207
235
  // Safe to assert on the results produced by the mocked responses
208
236
  ```
209
237
 
238
+ **Multiple test processes** can run concurrently - each gets a unique `runId` and their batches are isolated from each other.
239
+
210
240
  ## Describe Requests with Metadata
211
241
 
212
242
  `requestMock` accepts an optional third argument (`RequestMockOptions`) that is forwarded without modification to the MCP server. The most important field in that object is `metadata`, which lets the test process describe each request with the exact OpenAPI JSON Schema fragment, sample payloads, or test context that the AI client needs to build a response.
@@ -250,144 +280,202 @@ await mockClient.requestMock("/api/products", "GET", {
250
280
  - Keep the metadata JSON-serializable and deterministic; large binary blobs or class instances will be dropped.
251
281
  - Reuse helper functions to centralize schema definitions so each test only supplies the endpoint-specific instructions.
252
282
 
253
- ## MCP tools
283
+ ## MCP Tools
254
284
 
255
- Two tools keep the queue visible to AI agents and deliver mocks back to waiting tests:
285
+ The new architecture provides a richer set of tools with claim-based concurrency control:
256
286
 
257
- | Tool | Purpose | Response |
258
- | ------------------------- | ------------------------------------------ | ------------------------------------------------------- |
259
- | `get_pending_batches` | Lists queued batches with request metadata | JSON string (array of `{batchId, timestamp, requests}`) |
260
- | `provide_batch_mock_data` | Sends mock payloads for a specific batch | JSON string reporting success |
287
+ | Tool | Purpose | Input |
288
+ | ------------------------- | ----------------------------------------------- | ------------------------------------------ |
289
+ | `get_status` | Get daemon status (runs, pending, claimed) | None |
290
+ | `list_runs` | List all active test runs | None |
291
+ | `claim_next_batch` | Claim the next pending batch (with lease) | `{ runId?, leaseMs? }` |
292
+ | `get_batch` | Get details of a specific batch (read-only) | `{ batchId }` |
293
+ | `provide_batch_mock_data` | Provide mock data for a claimed batch | `{ batchId, claimToken, mocks }` |
294
+ | `release_batch` | Release a claimed batch without providing mocks | `{ batchId, claimToken, reason? }` |
261
295
 
262
- Example payload for `provide_batch_mock_data`:
296
+ ### Workflow
297
+
298
+ The new workflow uses **claim → provide** to prevent race conditions:
299
+
300
+ 1. **Claim a batch** - Call `claim_next_batch` to acquire a lease on a pending batch
301
+ 2. **Receive batch details** - Get `batchId`, `claimToken`, and `requests` array
302
+ 3. **Generate mocks** - Create mock responses for each request
303
+ 4. **Provide mocks** - Call `provide_batch_mock_data` with the claim token
263
304
 
264
305
  ```jsonc
306
+ // Step 1: Claim
265
307
  {
266
- "batchId": "batch-3",
267
- "mocks": [
268
- {
269
- "requestId": "req-7",
270
- "data": { "users": [{ "id": 1, "name": "Alice" }] }
271
- }
272
- ]
308
+ "name": "claim_next_batch",
309
+ "arguments": { "leaseMs": 30000 }
310
+ }
311
+ // Returns: { "batchId": "batch:abc:1", "claimToken": "xyz", "requests": [...] }
312
+
313
+ // Step 2: Provide
314
+ {
315
+ "name": "provide_batch_mock_data",
316
+ "arguments": {
317
+ "batchId": "batch:abc:1",
318
+ "claimToken": "xyz",
319
+ "mocks": [
320
+ { "requestId": "req-1", "data": { "id": 1, "name": "Alice" } }
321
+ ]
322
+ }
273
323
  }
274
324
  ```
275
325
 
326
+ **Lease expiration**: If you don't provide mocks within the lease time (default 30s), the batch is automatically released for another adapter to claim.
327
+
328
+ ## CLI Commands
329
+
330
+ | Command | Description |
331
+ | ------------------- | ----------------------------------------------------- |
332
+ | `mock-mcp adapter` | Start the MCP adapter (default, for MCP clients) |
333
+ | `mock-mcp daemon` | Start the daemon process (usually auto-started) |
334
+ | `mock-mcp status` | Show daemon status for current project |
335
+ | `mock-mcp stop` | Stop the daemon for current project |
336
+ | `mock-mcp help` | Show help |
337
+ | `mock-mcp version` | Show version |
338
+
339
+ Example usage:
340
+
341
+ ```bash
342
+ # Check if daemon is running
343
+ mock-mcp status
344
+
345
+ # Manually stop daemon
346
+ mock-mcp stop
347
+ ```
348
+
276
349
  ## Available APIs
277
350
 
278
351
  The library exports primitives so you can embed the workflow inside bespoke runners or scripts:
279
352
 
280
- - `TestMockMCPServer` starts and stops the WebSocket plus MCP tooling bridge programmatically.
281
- - `BatchMockCollector` provides a low-level batching client used directly inside test environments.
282
- - `BatchMockCollector.waitForPendingRequests()` waits for the currently pending mock requests to settle (resolves when all finish, rejects if any fail).
283
- - `connect(options)` instantiates `BatchMockCollector` and waits for the WebSocket connection to open.
353
+ ### Client APIs
354
+
355
+ - `connect(options?)` - Creates a `BatchMockCollector` and waits for daemon connection.
356
+ - `BatchMockCollector` - Low-level batching client for test environments.
357
+ - `BatchMockCollector.requestMock(endpoint, method, options?)` - Request mock data for an endpoint.
358
+ - `BatchMockCollector.waitForPendingRequests()` - Wait for pending requests to settle.
359
+ - `BatchMockCollector.getRunId()` - Get the unique run ID for this collector.
360
+
361
+ ### Server APIs
284
362
 
285
- Each class accepts logger overrides, timeout tweaks, and other ergonomics surfaced in the technical design.
363
+ - `MockMcpDaemon` - The daemon process that manages runs and batches.
364
+ - `runAdapter()` - Start the MCP adapter (stdio transport).
365
+ - `DaemonClient` - JSON-RPC client for communicating with the daemon.
366
+
367
+ ### Discovery APIs
368
+
369
+ - `ensureDaemonRunning(options?)` - Ensure daemon is running, start if needed.
370
+ - `resolveProjectRoot(startDir?)` - Find project root by searching for `.git` or `package.json`.
371
+ - `computeProjectId(projectRoot)` - Compute stable project ID from path.
372
+
373
+ Each class accepts logger overrides, timeout tweaks, and other ergonomics.
286
374
 
287
375
  ## Environment Variables
288
376
 
289
- | Variable | Description | Default |
290
- | ----------------- | ---------------------------------------------------------------------------- | ------- |
291
- | `MCP_SERVER_PORT` | Overrides the WebSocket port used by both the CLI and any spawned MCP host. | `3002` |
292
- | `MOCK_MCP` | Enables the test runner hook so intercepted requests are routed to mock-mcp. | unset |
377
+ | Variable | Description | Default |
378
+ | -------------------- | ------------------------------------------------------------------------ | ------------------ |
379
+ | `MOCK_MCP` | Enables the test runner hook so intercepted requests are routed to mock-mcp. | unset |
380
+ | `MOCK_MCP_CACHE_DIR` | Override the cache directory for daemon files (registry, socket, lock). | `~/.cache/mock-mcp`|
293
381
 
294
382
  ## How It Works
295
383
 
296
- Three collaborating processes share responsibilities while staying loosely coupled:
384
+ The new **Daemon + Adapter** architecture uses four collaborating processes:
297
385
 
298
- | Process | Responsibility | Technology | Communication |
299
- | ---------------- | ----------------------------------------------------- | ---------------------------------------- | ------------------------------------------ |
300
- | **Test Process** | Executes test cases and intercepts HTTP requests | Playwright/Puppeteer + WebSocket client | WebSocket → MCP Server |
301
- | **MCP Server** | Coordinates batches and forwards data between parties | Node.js + WebSocket server + MCP SDK | stdioMCP Client · WebSocket ↔ Test Flow |
302
- | **MCP Client** | Uses AI to produce mock data via MCP tools | Cursor / Claude Desktop / custom clients | MCP protocol MCP Server |
386
+ | Process | Responsibility | Technology | Communication |
387
+ | ---------------- | ----------------------------------------------------- | ---------------------------------------- | ------------------------------- |
388
+ | **Test Process** | Executes test cases and intercepts HTTP requests | Playwright/Puppeteer + BatchMockCollector| WebSocket over IPC Daemon |
389
+ | **Daemon** | Manages runs, batches, claims with lease control | Node.js + HTTP/WS on Unix socket | IPC ↔ Test & Adapter |
390
+ | **Adapter** | Bridges MCP protocol to daemon RPC | Node.js + MCP SDK (stdio) | stdio MCP Client, RPCDaemon|
391
+ | **MCP Client** | Uses AI to produce mock data via MCP tools | Cursor / Claude Desktop / custom clients | MCP protocol → Adapter |
303
392
 
304
- ### Data flow sequence clarifies message order
393
+ ### Data flow sequence with claim-based concurrency
305
394
 
306
395
  ```
307
- ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
308
- │ Test Process │ MCP Server MCP Client
309
- │ (Browser Test) │ (AI)
310
- └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
311
-
312
- │ 1. Start Test
313
- page.goto()
314
- ├───────────────────────────►│
315
-
316
- │ 2. Trigger concurrent
317
- requests
318
- fetch /api/users
319
- fetch /api/products
320
- fetch /api/orders
321
- (Promises pending)
322
-
323
- 3. setTimeout(0) batches
324
- BATCH_MOCK_REQUEST
325
- [req-1, req-2, req-3]
326
- ├═══════════════════════════►│
327
-
328
- Test paused... 4. Store batch in queue
329
- Awaiting mocks pendingBatches.set() │
330
-
331
- 5. Wait for MCP Client
332
- to call tools │
333
-
334
- │◄───────────────────────────┤
335
- 6. Tool Call: │
336
- get_pending_batches
337
-
338
- 7. Return batch info
339
- ├───────────────────────────►│
340
- [{batchId, requests}]
341
-
342
- 8. AI analyzes
343
- Generates mocks
344
-
345
- │◄───────────────────────────┤
346
- 9. Tool Call:
347
- provide_batch_mock_data
348
- {mocks: [...]}
349
-
350
- 10. BATCH_MOCK_RESPONSE
351
- [mock-1, mock-2, ...]
352
- │◄═══════════════════════════┤
353
-
354
- 11. Batch resolve
355
- │ req-1.resolve() │ │
356
- │ req-2.resolve() │ │
357
- │ req-3.resolve() │ │
358
- │ │ │
359
- │ 12. Test continues │ │
360
- │ Assertions & │ │
361
- │ Verification │ │
362
- │ │ │
363
- │ 13. Test Complete ✓ │ │
364
- ▼ ▼ ▼
396
+ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
397
+ │ Test Process │ Daemon Adapter │ │ MCP Client
398
+ │ (Browser Test) │ (per-project) (per MCP client) │ │ (AI)
399
+ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘
400
+
401
+ │ 1. Connect via IPC
402
+ HELLO_TEST
403
+ ├════════════════════════►│
404
+
405
+ │ 2. HELLO_ACK
406
+ │◄════════════════════════┤
407
+
408
+ 3. BATCH_MOCK_REQUEST
409
+ [req-1, req-2, ...]
410
+ ├════════════════════════►│
411
+
412
+ Test paused... │ 4. Store in pending
413
+ Awaiting mocks │ queue
414
+
415
+ │ │◄────────────────────────┤
416
+ 5. claim_next_batch │
417
+
418
+ │◄────────────────────────┤
419
+ 6. RPC: claimNextBatch
420
+
421
+ ├────────────────────────►│
422
+ 7. {batch, claimToken}
423
+ │ │ │
424
+ ├────────────────────────►│
425
+ 8. Return batch info │
426
+
427
+ │ 9. AI generates
428
+ │ │ mock data │
429
+
430
+ │◄────────────────────────┤
431
+ │ 10. provide_batch_
432
+ mock_data │
433
+
434
+ │◄────────────────────────┤ │
435
+ 11. RPC: provideBatch
436
+ + claimToken
437
+
438
+ 12. BATCH_MOCK_RESULT
439
+ [mock-1, mock-2]
440
+ │◄════════════════════════┤
441
+ │ │ │
442
+ 13. Resolve promises
443
+ Test continues
444
+ ▼ ▼ ▼ ▼
365
445
 
366
446
  Protocol Summary:
367
447
  ─────────────────
368
- - Test Process ←→ MCP Server: WebSocket/IPC
369
- Message types: BATCH_MOCK_REQUEST, BATCH_MOCK_RESPONSE
448
+ - Test Process ←→ Daemon: WebSocket over IPC (Unix socket / Named pipe)
449
+ Message types: HELLO_TEST, BATCH_MOCK_REQUEST, BATCH_MOCK_RESULT
450
+
451
+ - Adapter ←→ Daemon: HTTP JSON-RPC over IPC
452
+ Methods: claimNextBatch, provideBatch, getStatus, listRuns
370
453
 
371
- - MCP Server ←→ MCP Client: Stdio/JSON-RPC (MCP Protocol)
372
- Tools: get_pending_batches, provide_batch_mock_data
454
+ - MCP Client ←→ Adapter: MCP protocol (stdio)
455
+ Tools: claim_next_batch, provide_batch_mock_data, get_status, list_runs
373
456
 
374
457
  Key Features:
375
458
  ──────────────
376
- Batch processing of concurrent requests
377
- Non-blocking test execution during AI mock generation
378
- Real-time mock data generation by AI
379
- Automatic promise resolution after mock provision
459
+ uses IPC instead of TCP - No port conflicts
460
+ Multi-client support - multiple MCP clients can run simultaneously
461
+ Claim-based concurrency - prevents race conditions on batches
462
+ Lease expiration - auto-recovery if adapter crashes
463
+ ✓ Multi-run isolation - concurrent test processes are isolated
464
+ ✓ Auto-discovery - no manual configuration needed
380
465
  ```
381
466
 
382
467
  ## Use the development scripts
383
468
 
384
469
  ```bash
385
- pnpm test # runs Vitest suites
386
- pnpm dev # tsx watch mode for the CLI
387
- pnpm lint # eslint --ext .ts
470
+ yarn test # runs Vitest suites
471
+ yarn test:concurrency # runs concurrency tests specifically
472
+ yarn dev # tsx watch mode for the CLI
473
+ yarn dev:adapter # tsx watch mode for adapter
474
+ yarn lint # eslint --ext .ts
475
+ yarn build # compile TypeScript
388
476
  ```
389
477
 
390
- Vitest suites spin up ephemeral WebSocket servers, so avoid running them concurrently with an already running instance on the same port.
478
+ Tests create isolated daemon instances with temporary cache directories, so they can run safely without affecting your development environment.
391
479
 
392
480
  ## License
393
481