mock-mcp 0.5.0 → 0.5.1

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.
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  var http = require('http');
4
+ var fssync = require('fs');
4
5
  var path = require('path');
5
6
  var crypto = require('crypto');
6
7
  var url = require('url');
7
8
  var WebSocket = require('ws');
8
9
  var fs = require('fs/promises');
9
- var fssync = require('fs');
10
10
  var os = require('os');
11
11
  var child_process = require('child_process');
12
12
  var module$1 = require('module');
@@ -14,11 +14,11 @@ var module$1 = require('module');
14
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
15
 
16
16
  var http__default = /*#__PURE__*/_interopDefault(http);
17
+ var fssync__default = /*#__PURE__*/_interopDefault(fssync);
17
18
  var path__default = /*#__PURE__*/_interopDefault(path);
18
19
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
19
20
  var WebSocket__default = /*#__PURE__*/_interopDefault(WebSocket);
20
21
  var fs__default = /*#__PURE__*/_interopDefault(fs);
21
- var fssync__default = /*#__PURE__*/_interopDefault(fssync);
22
22
  var os__default = /*#__PURE__*/_interopDefault(os);
23
23
 
24
24
  var __importMetaUrl = (function() {
@@ -62,6 +62,27 @@ var __curDirname = (() => {
62
62
  }
63
63
  return process.cwd();
64
64
  })();
65
+ function hasValidProjectMarker(dir) {
66
+ try {
67
+ const gitPath = path__default.default.join(dir, ".git");
68
+ try {
69
+ const stat = fssync__default.default.statSync(gitPath);
70
+ if (stat.isDirectory() || stat.isFile()) {
71
+ return true;
72
+ }
73
+ } catch {
74
+ }
75
+ const pkgPath = path__default.default.join(dir, "package.json");
76
+ try {
77
+ fssync__default.default.accessSync(pkgPath, fssync__default.default.constants.F_OK);
78
+ return true;
79
+ } catch {
80
+ }
81
+ return false;
82
+ } catch {
83
+ return false;
84
+ }
85
+ }
65
86
  function resolveProjectRoot(startDir = process.cwd()) {
66
87
  let current = path__default.default.resolve(startDir);
67
88
  const root = path__default.default.parse(current).root;
@@ -189,7 +210,28 @@ function getDaemonEntryPath() {
189
210
  return path__default.default.join(process.cwd(), "dist", "index.js");
190
211
  }
191
212
  async function ensureDaemonRunning(opts = {}) {
192
- const projectRoot = opts.projectRoot ?? resolveProjectRoot();
213
+ let projectRoot = opts.projectRoot ?? resolveProjectRoot();
214
+ if (!hasValidProjectMarker(projectRoot)) {
215
+ const resolved = resolveProjectRoot(projectRoot);
216
+ if (resolved !== projectRoot && hasValidProjectMarker(resolved)) {
217
+ console.error(`[mock-mcp] Warning: projectRoot "${projectRoot}" doesn't look like a project root`);
218
+ console.error(`[mock-mcp] Found .git/package.json at: "${resolved}"`);
219
+ projectRoot = resolved;
220
+ } else {
221
+ console.error(`[mock-mcp] \u26A0\uFE0F WARNING: Could not find a valid project root!`);
222
+ console.error(`[mock-mcp] Current path: "${projectRoot}"`);
223
+ console.error(`[mock-mcp] This path doesn't contain .git or package.json.`);
224
+ console.error(`[mock-mcp] This may cause project mismatch issues.`);
225
+ console.error(`[mock-mcp] `);
226
+ console.error(`[mock-mcp] For MCP adapters, please specify --project-root explicitly:`);
227
+ console.error(`[mock-mcp] mock-mcp adapter --project-root /path/to/your/project`);
228
+ console.error(`[mock-mcp] `);
229
+ console.error(`[mock-mcp] In your MCP client config (Cursor, Claude Desktop, etc.):`);
230
+ console.error(`[mock-mcp] {`);
231
+ console.error(`[mock-mcp] "args": ["-y", "mock-mcp", "adapter", "--project-root", "/path/to/your/project"]`);
232
+ console.error(`[mock-mcp] }`);
233
+ }
234
+ }
193
235
  const projectId = computeProjectId(projectRoot);
194
236
  const { base, registryPath, lockPath, ipcPath } = getPaths(
195
237
  projectId,
@@ -364,11 +406,19 @@ var BatchMockCollector = class {
364
406
  }
365
407
  /**
366
408
  * Resolve projectRoot from options.
367
- * Priority: projectRoot > filePath > undefined (auto-detect)
409
+ * Priority: projectRoot (if valid) > filePath > projectRoot (fallback) > undefined (auto-detect)
410
+ *
411
+ * A projectRoot is "valid" if it contains .git or package.json. This prevents
412
+ * accidentally using a wrong directory (e.g., user's home directory) when the
413
+ * caller mistakenly passes process.cwd() as projectRoot.
368
414
  */
369
415
  resolveProjectRootFromOptions(options) {
370
416
  if (options.projectRoot) {
371
- return options.projectRoot;
417
+ const hasGit = this.hasGitOrPackageJson(options.projectRoot);
418
+ if (hasGit) {
419
+ return options.projectRoot;
420
+ }
421
+ this.logger.warn(`[mock-mcp] Warning: projectRoot "${options.projectRoot}" doesn't contain .git or package.json`);
372
422
  }
373
423
  if (options.filePath) {
374
424
  let filePath = options.filePath;
@@ -387,8 +437,36 @@ var BatchMockCollector = class {
387
437
  this.logger.log(`[mock-mcp] projectRoot: ${resolved}`);
388
438
  return resolved;
389
439
  }
440
+ if (options.projectRoot) {
441
+ this.logger.warn(`[mock-mcp] Warning: Using projectRoot "${options.projectRoot}" despite missing .git/package.json`);
442
+ return options.projectRoot;
443
+ }
390
444
  return void 0;
391
445
  }
446
+ /**
447
+ * Check if a directory contains .git or package.json
448
+ */
449
+ hasGitOrPackageJson(dir) {
450
+ try {
451
+ const gitPath = path__default.default.join(dir, ".git");
452
+ const pkgPath = path__default.default.join(dir, "package.json");
453
+ try {
454
+ const stat = fssync__default.default.statSync(gitPath);
455
+ if (stat.isDirectory() || stat.isFile()) {
456
+ return true;
457
+ }
458
+ } catch {
459
+ }
460
+ try {
461
+ fssync__default.default.accessSync(pkgPath, fssync__default.default.constants.F_OK);
462
+ return true;
463
+ } catch {
464
+ }
465
+ return false;
466
+ } catch {
467
+ return false;
468
+ }
469
+ }
392
470
  /**
393
471
  * Ensures the underlying connection is ready for use.
394
472
  */
@@ -1,5 +1,4 @@
1
- import { D as DaemonRegistry } from '../discovery-Dc2LdF8q.cjs';
2
- import { R as ResolvedMock } from '../types-BKREdsyr.cjs';
1
+ import { R as ResolvedMock, D as DaemonRegistry } from '../types-bEGXLBF0.cjs';
3
2
  import 'node:fs';
4
3
 
5
4
  /**
@@ -120,9 +119,17 @@ declare class BatchMockCollector {
120
119
  constructor(options?: BatchMockCollectorOptions);
121
120
  /**
122
121
  * Resolve projectRoot from options.
123
- * Priority: projectRoot > filePath > undefined (auto-detect)
122
+ * Priority: projectRoot (if valid) > filePath > projectRoot (fallback) > undefined (auto-detect)
123
+ *
124
+ * A projectRoot is "valid" if it contains .git or package.json. This prevents
125
+ * accidentally using a wrong directory (e.g., user's home directory) when the
126
+ * caller mistakenly passes process.cwd() as projectRoot.
124
127
  */
125
128
  private resolveProjectRootFromOptions;
129
+ /**
130
+ * Check if a directory contains .git or package.json
131
+ */
132
+ private hasGitOrPackageJson;
126
133
  /**
127
134
  * Ensures the underlying connection is ready for use.
128
135
  */
@@ -1,5 +1,4 @@
1
- import { D as DaemonRegistry } from '../discovery-Dc2LdF8q.js';
2
- import { R as ResolvedMock } from '../types-BKREdsyr.js';
1
+ import { R as ResolvedMock, D as DaemonRegistry } from '../types-bEGXLBF0.js';
3
2
  import 'node:fs';
4
3
 
5
4
  /**
@@ -120,9 +119,17 @@ declare class BatchMockCollector {
120
119
  constructor(options?: BatchMockCollectorOptions);
121
120
  /**
122
121
  * Resolve projectRoot from options.
123
- * Priority: projectRoot > filePath > undefined (auto-detect)
122
+ * Priority: projectRoot (if valid) > filePath > projectRoot (fallback) > undefined (auto-detect)
123
+ *
124
+ * A projectRoot is "valid" if it contains .git or package.json. This prevents
125
+ * accidentally using a wrong directory (e.g., user's home directory) when the
126
+ * caller mistakenly passes process.cwd() as projectRoot.
124
127
  */
125
128
  private resolveProjectRootFromOptions;
129
+ /**
130
+ * Check if a directory contains .git or package.json
131
+ */
132
+ private hasGitOrPackageJson;
126
133
  /**
127
134
  * Ensures the underlying connection is ready for use.
128
135
  */
@@ -1,10 +1,10 @@
1
1
  import http from 'http';
2
+ import fssync from 'fs';
2
3
  import path from 'path';
3
4
  import crypto from 'crypto';
4
5
  import { fileURLToPath, pathToFileURL } from 'url';
5
6
  import WebSocket from 'ws';
6
7
  import fs from 'fs/promises';
7
- import fssync from 'fs';
8
8
  import os from 'os';
9
9
  import { spawn } from 'child_process';
10
10
  import { createRequire } from 'module';
@@ -22,6 +22,27 @@ var __curDirname = (() => {
22
22
  }
23
23
  return process.cwd();
24
24
  })();
25
+ function hasValidProjectMarker(dir) {
26
+ try {
27
+ const gitPath = path.join(dir, ".git");
28
+ try {
29
+ const stat = fssync.statSync(gitPath);
30
+ if (stat.isDirectory() || stat.isFile()) {
31
+ return true;
32
+ }
33
+ } catch {
34
+ }
35
+ const pkgPath = path.join(dir, "package.json");
36
+ try {
37
+ fssync.accessSync(pkgPath, fssync.constants.F_OK);
38
+ return true;
39
+ } catch {
40
+ }
41
+ return false;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
25
46
  function resolveProjectRoot(startDir = process.cwd()) {
26
47
  let current = path.resolve(startDir);
27
48
  const root = path.parse(current).root;
@@ -149,7 +170,28 @@ function getDaemonEntryPath() {
149
170
  return path.join(process.cwd(), "dist", "index.js");
150
171
  }
151
172
  async function ensureDaemonRunning(opts = {}) {
152
- const projectRoot = opts.projectRoot ?? resolveProjectRoot();
173
+ let projectRoot = opts.projectRoot ?? resolveProjectRoot();
174
+ if (!hasValidProjectMarker(projectRoot)) {
175
+ const resolved = resolveProjectRoot(projectRoot);
176
+ if (resolved !== projectRoot && hasValidProjectMarker(resolved)) {
177
+ console.error(`[mock-mcp] Warning: projectRoot "${projectRoot}" doesn't look like a project root`);
178
+ console.error(`[mock-mcp] Found .git/package.json at: "${resolved}"`);
179
+ projectRoot = resolved;
180
+ } else {
181
+ console.error(`[mock-mcp] \u26A0\uFE0F WARNING: Could not find a valid project root!`);
182
+ console.error(`[mock-mcp] Current path: "${projectRoot}"`);
183
+ console.error(`[mock-mcp] This path doesn't contain .git or package.json.`);
184
+ console.error(`[mock-mcp] This may cause project mismatch issues.`);
185
+ console.error(`[mock-mcp] `);
186
+ console.error(`[mock-mcp] For MCP adapters, please specify --project-root explicitly:`);
187
+ console.error(`[mock-mcp] mock-mcp adapter --project-root /path/to/your/project`);
188
+ console.error(`[mock-mcp] `);
189
+ console.error(`[mock-mcp] In your MCP client config (Cursor, Claude Desktop, etc.):`);
190
+ console.error(`[mock-mcp] {`);
191
+ console.error(`[mock-mcp] "args": ["-y", "mock-mcp", "adapter", "--project-root", "/path/to/your/project"]`);
192
+ console.error(`[mock-mcp] }`);
193
+ }
194
+ }
153
195
  const projectId = computeProjectId(projectRoot);
154
196
  const { base, registryPath, lockPath, ipcPath } = getPaths(
155
197
  projectId,
@@ -324,11 +366,19 @@ var BatchMockCollector = class {
324
366
  }
325
367
  /**
326
368
  * Resolve projectRoot from options.
327
- * Priority: projectRoot > filePath > undefined (auto-detect)
369
+ * Priority: projectRoot (if valid) > filePath > projectRoot (fallback) > undefined (auto-detect)
370
+ *
371
+ * A projectRoot is "valid" if it contains .git or package.json. This prevents
372
+ * accidentally using a wrong directory (e.g., user's home directory) when the
373
+ * caller mistakenly passes process.cwd() as projectRoot.
328
374
  */
329
375
  resolveProjectRootFromOptions(options) {
330
376
  if (options.projectRoot) {
331
- return options.projectRoot;
377
+ const hasGit = this.hasGitOrPackageJson(options.projectRoot);
378
+ if (hasGit) {
379
+ return options.projectRoot;
380
+ }
381
+ this.logger.warn(`[mock-mcp] Warning: projectRoot "${options.projectRoot}" doesn't contain .git or package.json`);
332
382
  }
333
383
  if (options.filePath) {
334
384
  let filePath = options.filePath;
@@ -347,8 +397,36 @@ var BatchMockCollector = class {
347
397
  this.logger.log(`[mock-mcp] projectRoot: ${resolved}`);
348
398
  return resolved;
349
399
  }
400
+ if (options.projectRoot) {
401
+ this.logger.warn(`[mock-mcp] Warning: Using projectRoot "${options.projectRoot}" despite missing .git/package.json`);
402
+ return options.projectRoot;
403
+ }
350
404
  return void 0;
351
405
  }
406
+ /**
407
+ * Check if a directory contains .git or package.json
408
+ */
409
+ hasGitOrPackageJson(dir) {
410
+ try {
411
+ const gitPath = path.join(dir, ".git");
412
+ const pkgPath = path.join(dir, "package.json");
413
+ try {
414
+ const stat = fssync.statSync(gitPath);
415
+ if (stat.isDirectory() || stat.isFile()) {
416
+ return true;
417
+ }
418
+ } catch {
419
+ }
420
+ try {
421
+ fssync.accessSync(pkgPath, fssync.constants.F_OK);
422
+ return true;
423
+ } catch {
424
+ }
425
+ return false;
426
+ } catch {
427
+ return false;
428
+ }
429
+ }
352
430
  /**
353
431
  * Ensures the underlying connection is ready for use.
354
432
  */
@@ -1,12 +1,12 @@
1
1
  'use strict';
2
2
 
3
3
  var http = require('http');
4
+ var fssync = require('fs');
4
5
  var path = require('path');
5
6
  var crypto = require('crypto');
6
7
  var url = require('url');
7
8
  var WebSocket = require('ws');
8
9
  var fs = require('fs/promises');
9
- var fssync = require('fs');
10
10
  var os = require('os');
11
11
  var child_process = require('child_process');
12
12
  var module$1 = require('module');
@@ -14,11 +14,11 @@ var module$1 = require('module');
14
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
15
15
 
16
16
  var http__default = /*#__PURE__*/_interopDefault(http);
17
+ var fssync__default = /*#__PURE__*/_interopDefault(fssync);
17
18
  var path__default = /*#__PURE__*/_interopDefault(path);
18
19
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
19
20
  var WebSocket__default = /*#__PURE__*/_interopDefault(WebSocket);
20
21
  var fs__default = /*#__PURE__*/_interopDefault(fs);
21
- var fssync__default = /*#__PURE__*/_interopDefault(fssync);
22
22
  var os__default = /*#__PURE__*/_interopDefault(os);
23
23
 
24
24
  var __importMetaUrl = (function() {
@@ -62,6 +62,27 @@ var __curDirname = (() => {
62
62
  }
63
63
  return process.cwd();
64
64
  })();
65
+ function hasValidProjectMarker(dir) {
66
+ try {
67
+ const gitPath = path__default.default.join(dir, ".git");
68
+ try {
69
+ const stat = fssync__default.default.statSync(gitPath);
70
+ if (stat.isDirectory() || stat.isFile()) {
71
+ return true;
72
+ }
73
+ } catch {
74
+ }
75
+ const pkgPath = path__default.default.join(dir, "package.json");
76
+ try {
77
+ fssync__default.default.accessSync(pkgPath, fssync__default.default.constants.F_OK);
78
+ return true;
79
+ } catch {
80
+ }
81
+ return false;
82
+ } catch {
83
+ return false;
84
+ }
85
+ }
65
86
  function resolveProjectRoot(startDir = process.cwd()) {
66
87
  let current = path__default.default.resolve(startDir);
67
88
  const root = path__default.default.parse(current).root;
@@ -189,7 +210,28 @@ function getDaemonEntryPath() {
189
210
  return path__default.default.join(process.cwd(), "dist", "index.js");
190
211
  }
191
212
  async function ensureDaemonRunning(opts = {}) {
192
- const projectRoot = opts.projectRoot ?? resolveProjectRoot();
213
+ let projectRoot = opts.projectRoot ?? resolveProjectRoot();
214
+ if (!hasValidProjectMarker(projectRoot)) {
215
+ const resolved = resolveProjectRoot(projectRoot);
216
+ if (resolved !== projectRoot && hasValidProjectMarker(resolved)) {
217
+ console.error(`[mock-mcp] Warning: projectRoot "${projectRoot}" doesn't look like a project root`);
218
+ console.error(`[mock-mcp] Found .git/package.json at: "${resolved}"`);
219
+ projectRoot = resolved;
220
+ } else {
221
+ console.error(`[mock-mcp] \u26A0\uFE0F WARNING: Could not find a valid project root!`);
222
+ console.error(`[mock-mcp] Current path: "${projectRoot}"`);
223
+ console.error(`[mock-mcp] This path doesn't contain .git or package.json.`);
224
+ console.error(`[mock-mcp] This may cause project mismatch issues.`);
225
+ console.error(`[mock-mcp] `);
226
+ console.error(`[mock-mcp] For MCP adapters, please specify --project-root explicitly:`);
227
+ console.error(`[mock-mcp] mock-mcp adapter --project-root /path/to/your/project`);
228
+ console.error(`[mock-mcp] `);
229
+ console.error(`[mock-mcp] In your MCP client config (Cursor, Claude Desktop, etc.):`);
230
+ console.error(`[mock-mcp] {`);
231
+ console.error(`[mock-mcp] "args": ["-y", "mock-mcp", "adapter", "--project-root", "/path/to/your/project"]`);
232
+ console.error(`[mock-mcp] }`);
233
+ }
234
+ }
193
235
  const projectId = computeProjectId(projectRoot);
194
236
  const { base, registryPath, lockPath, ipcPath } = getPaths(
195
237
  projectId,
@@ -364,11 +406,19 @@ var BatchMockCollector = class {
364
406
  }
365
407
  /**
366
408
  * Resolve projectRoot from options.
367
- * Priority: projectRoot > filePath > undefined (auto-detect)
409
+ * Priority: projectRoot (if valid) > filePath > projectRoot (fallback) > undefined (auto-detect)
410
+ *
411
+ * A projectRoot is "valid" if it contains .git or package.json. This prevents
412
+ * accidentally using a wrong directory (e.g., user's home directory) when the
413
+ * caller mistakenly passes process.cwd() as projectRoot.
368
414
  */
369
415
  resolveProjectRootFromOptions(options) {
370
416
  if (options.projectRoot) {
371
- return options.projectRoot;
417
+ const hasGit = this.hasGitOrPackageJson(options.projectRoot);
418
+ if (hasGit) {
419
+ return options.projectRoot;
420
+ }
421
+ this.logger.warn(`[mock-mcp] Warning: projectRoot "${options.projectRoot}" doesn't contain .git or package.json`);
372
422
  }
373
423
  if (options.filePath) {
374
424
  let filePath = options.filePath;
@@ -387,8 +437,36 @@ var BatchMockCollector = class {
387
437
  this.logger.log(`[mock-mcp] projectRoot: ${resolved}`);
388
438
  return resolved;
389
439
  }
440
+ if (options.projectRoot) {
441
+ this.logger.warn(`[mock-mcp] Warning: Using projectRoot "${options.projectRoot}" despite missing .git/package.json`);
442
+ return options.projectRoot;
443
+ }
390
444
  return void 0;
391
445
  }
446
+ /**
447
+ * Check if a directory contains .git or package.json
448
+ */
449
+ hasGitOrPackageJson(dir) {
450
+ try {
451
+ const gitPath = path__default.default.join(dir, ".git");
452
+ const pkgPath = path__default.default.join(dir, "package.json");
453
+ try {
454
+ const stat = fssync__default.default.statSync(gitPath);
455
+ if (stat.isDirectory() || stat.isFile()) {
456
+ return true;
457
+ }
458
+ } catch {
459
+ }
460
+ try {
461
+ fssync__default.default.accessSync(pkgPath, fssync__default.default.constants.F_OK);
462
+ return true;
463
+ } catch {
464
+ }
465
+ return false;
466
+ } catch {
467
+ return false;
468
+ }
469
+ }
392
470
  /**
393
471
  * Ensures the underlying connection is ready for use.
394
472
  */
@@ -1,4 +1,3 @@
1
1
  export { B as BatchMockCollector, a as BatchMockCollectorOptions, ConnectOptions, MockClient, R as RequestMockOptions, connect } from './connect.cjs';
2
- import '../discovery-Dc2LdF8q.cjs';
2
+ import '../types-bEGXLBF0.cjs';
3
3
  import 'node:fs';
4
- import '../types-BKREdsyr.cjs';
@@ -1,4 +1,3 @@
1
1
  export { B as BatchMockCollector, a as BatchMockCollectorOptions, ConnectOptions, MockClient, R as RequestMockOptions, connect } from './connect.js';
2
- import '../discovery-Dc2LdF8q.js';
2
+ import '../types-bEGXLBF0.js';
3
3
  import 'node:fs';
4
- import '../types-BKREdsyr.js';
@@ -1,10 +1,10 @@
1
1
  import http from 'http';
2
+ import fssync from 'fs';
2
3
  import path from 'path';
3
4
  import crypto from 'crypto';
4
5
  import { fileURLToPath, pathToFileURL } from 'url';
5
6
  import WebSocket from 'ws';
6
7
  import fs from 'fs/promises';
7
- import fssync from 'fs';
8
8
  import os from 'os';
9
9
  import { spawn } from 'child_process';
10
10
  import { createRequire } from 'module';
@@ -22,6 +22,27 @@ var __curDirname = (() => {
22
22
  }
23
23
  return process.cwd();
24
24
  })();
25
+ function hasValidProjectMarker(dir) {
26
+ try {
27
+ const gitPath = path.join(dir, ".git");
28
+ try {
29
+ const stat = fssync.statSync(gitPath);
30
+ if (stat.isDirectory() || stat.isFile()) {
31
+ return true;
32
+ }
33
+ } catch {
34
+ }
35
+ const pkgPath = path.join(dir, "package.json");
36
+ try {
37
+ fssync.accessSync(pkgPath, fssync.constants.F_OK);
38
+ return true;
39
+ } catch {
40
+ }
41
+ return false;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
25
46
  function resolveProjectRoot(startDir = process.cwd()) {
26
47
  let current = path.resolve(startDir);
27
48
  const root = path.parse(current).root;
@@ -149,7 +170,28 @@ function getDaemonEntryPath() {
149
170
  return path.join(process.cwd(), "dist", "index.js");
150
171
  }
151
172
  async function ensureDaemonRunning(opts = {}) {
152
- const projectRoot = opts.projectRoot ?? resolveProjectRoot();
173
+ let projectRoot = opts.projectRoot ?? resolveProjectRoot();
174
+ if (!hasValidProjectMarker(projectRoot)) {
175
+ const resolved = resolveProjectRoot(projectRoot);
176
+ if (resolved !== projectRoot && hasValidProjectMarker(resolved)) {
177
+ console.error(`[mock-mcp] Warning: projectRoot "${projectRoot}" doesn't look like a project root`);
178
+ console.error(`[mock-mcp] Found .git/package.json at: "${resolved}"`);
179
+ projectRoot = resolved;
180
+ } else {
181
+ console.error(`[mock-mcp] \u26A0\uFE0F WARNING: Could not find a valid project root!`);
182
+ console.error(`[mock-mcp] Current path: "${projectRoot}"`);
183
+ console.error(`[mock-mcp] This path doesn't contain .git or package.json.`);
184
+ console.error(`[mock-mcp] This may cause project mismatch issues.`);
185
+ console.error(`[mock-mcp] `);
186
+ console.error(`[mock-mcp] For MCP adapters, please specify --project-root explicitly:`);
187
+ console.error(`[mock-mcp] mock-mcp adapter --project-root /path/to/your/project`);
188
+ console.error(`[mock-mcp] `);
189
+ console.error(`[mock-mcp] In your MCP client config (Cursor, Claude Desktop, etc.):`);
190
+ console.error(`[mock-mcp] {`);
191
+ console.error(`[mock-mcp] "args": ["-y", "mock-mcp", "adapter", "--project-root", "/path/to/your/project"]`);
192
+ console.error(`[mock-mcp] }`);
193
+ }
194
+ }
153
195
  const projectId = computeProjectId(projectRoot);
154
196
  const { base, registryPath, lockPath, ipcPath } = getPaths(
155
197
  projectId,
@@ -324,11 +366,19 @@ var BatchMockCollector = class {
324
366
  }
325
367
  /**
326
368
  * Resolve projectRoot from options.
327
- * Priority: projectRoot > filePath > undefined (auto-detect)
369
+ * Priority: projectRoot (if valid) > filePath > projectRoot (fallback) > undefined (auto-detect)
370
+ *
371
+ * A projectRoot is "valid" if it contains .git or package.json. This prevents
372
+ * accidentally using a wrong directory (e.g., user's home directory) when the
373
+ * caller mistakenly passes process.cwd() as projectRoot.
328
374
  */
329
375
  resolveProjectRootFromOptions(options) {
330
376
  if (options.projectRoot) {
331
- return options.projectRoot;
377
+ const hasGit = this.hasGitOrPackageJson(options.projectRoot);
378
+ if (hasGit) {
379
+ return options.projectRoot;
380
+ }
381
+ this.logger.warn(`[mock-mcp] Warning: projectRoot "${options.projectRoot}" doesn't contain .git or package.json`);
332
382
  }
333
383
  if (options.filePath) {
334
384
  let filePath = options.filePath;
@@ -347,8 +397,36 @@ var BatchMockCollector = class {
347
397
  this.logger.log(`[mock-mcp] projectRoot: ${resolved}`);
348
398
  return resolved;
349
399
  }
400
+ if (options.projectRoot) {
401
+ this.logger.warn(`[mock-mcp] Warning: Using projectRoot "${options.projectRoot}" despite missing .git/package.json`);
402
+ return options.projectRoot;
403
+ }
350
404
  return void 0;
351
405
  }
406
+ /**
407
+ * Check if a directory contains .git or package.json
408
+ */
409
+ hasGitOrPackageJson(dir) {
410
+ try {
411
+ const gitPath = path.join(dir, ".git");
412
+ const pkgPath = path.join(dir, "package.json");
413
+ try {
414
+ const stat = fssync.statSync(gitPath);
415
+ if (stat.isDirectory() || stat.isFile()) {
416
+ return true;
417
+ }
418
+ } catch {
419
+ }
420
+ try {
421
+ fssync.accessSync(pkgPath, fssync.constants.F_OK);
422
+ return true;
423
+ } catch {
424
+ }
425
+ return false;
426
+ } catch {
427
+ return false;
428
+ }
429
+ }
352
430
  /**
353
431
  * Ensures the underlying connection is ready for use.
354
432
  */