metheus-governance-mcp-cli 0.2.42 → 0.2.44

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 (2) hide show
  1. package/cli.mjs +55 -14
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -683,12 +683,18 @@ function resolveWorkspaceDirForRequest(defaultWorkspaceDir, requestObj, toolArgs
683
683
  if (strongRequestResolved) {
684
684
  return strongRequestResolved;
685
685
  }
686
- if (strongEnvResolved) {
687
- return strongEnvResolved;
688
- }
689
686
  if (weakRequestResolved) {
687
+ // Prefer client-provided current workspace over fallback env, unless request resolves to home.
688
+ if (isHomeWorkspaceRoot(weakRequestResolved)) {
689
+ if (strongEnvResolved && !isHomeWorkspaceRoot(strongEnvResolved)) {
690
+ return strongEnvResolved;
691
+ }
692
+ }
690
693
  return weakRequestResolved;
691
694
  }
695
+ if (strongEnvResolved) {
696
+ return strongEnvResolved;
697
+ }
692
698
 
693
699
  const localPreferredCandidates = [
694
700
  defaultWorkspaceDir,
@@ -2749,11 +2755,11 @@ function syncCtxpackToLocalCache({
2749
2755
  ? metaPath
2750
2756
  : path.join(resolvedWorkspaceDir, CTXPACK_META_FILENAME);
2751
2757
 
2752
- if (!workspaceSignalTrusted && !isHomeFallback) {
2758
+ if (!workspaceSignalTrusted) {
2753
2759
  return {
2754
2760
  sync_status: "guarded",
2755
2761
  sync_message:
2756
- "Workspace signal is missing in auto mode. Guardrail blocked ctxpack local write to avoid wrong folder sync.",
2762
+ "Workspace signal is missing in auto mode. Guardrail blocked ctxpack local write.",
2757
2763
  local_path: cacheDir,
2758
2764
  workspace_path: resolvedWorkspaceDir,
2759
2765
  local_file_count: 0,
@@ -3632,6 +3638,15 @@ function shouldUseSafeToolAliasesForClient(initParamsRaw) {
3632
3638
  return name.includes("cursor") || name.includes("antigravity");
3633
3639
  }
3634
3640
 
3641
+ function canTrustProcessCwdForClient(clientNameRaw) {
3642
+ const name = String(clientNameRaw || "").trim().toLowerCase();
3643
+ if (!name) return false;
3644
+ // Codex app-server may not pass workspace signals reliably; never trust bare process.cwd().
3645
+ if (name.includes("codex")) return false;
3646
+ // VS Code forks generally spawn MCP in active workspace folder.
3647
+ return name.includes("cursor") || name.includes("antigravity");
3648
+ }
3649
+
3635
3650
  function displayToolNameForClient(canonicalName, useSafeToolAliases = false) {
3636
3651
  const canonical = String(canonicalName || "").trim();
3637
3652
  if (!canonical) return "";
@@ -4216,6 +4231,7 @@ async function runProxy(flags) {
4216
4231
  let sessionUseSafeToolAliases = false;
4217
4232
  let sessionToolAliasToCanonical = new Map();
4218
4233
  let sessionToolCanonicalToAlias = new Map();
4234
+ let sessionClientName = "";
4219
4235
 
4220
4236
  // Proxy-initiated requests (e.g., roots/list) pending client responses.
4221
4237
  const pendingProxyRequests = new Map(); // id → callback(responseObj)
@@ -4347,8 +4363,13 @@ async function runProxy(flags) {
4347
4363
  return;
4348
4364
  }
4349
4365
 
4350
- if (isJsonRpcMethod(requestObj, "initialize") && shouldUseSafeToolAliasesForClient(requestObj?.params)) {
4351
- sessionUseSafeToolAliases = true;
4366
+ if (isJsonRpcMethod(requestObj, "initialize")) {
4367
+ const initParams = safeObject(requestObj?.params);
4368
+ const initClientInfo = safeObject(initParams.clientInfo);
4369
+ sessionClientName = String(initClientInfo.name || "").trim().toLowerCase();
4370
+ if (shouldUseSafeToolAliasesForClient(initParams)) {
4371
+ sessionUseSafeToolAliases = true;
4372
+ }
4352
4373
  }
4353
4374
  if (sessionUseSafeToolAliases) {
4354
4375
  requestObj = rewriteAliasedToolCallToCanonical(requestObj, sessionToolAliasToCanonical);
@@ -4374,10 +4395,13 @@ async function runProxy(flags) {
4374
4395
  }
4375
4396
  if (!sessionWorkspaceDir) {
4376
4397
  const currentCwdCandidate = sanitizeWorkspaceCandidate(process.cwd());
4377
- if (currentCwdCandidate && !isHomeWorkspaceRoot(currentCwdCandidate)) {
4398
+ if (
4399
+ currentCwdCandidate &&
4400
+ !isHomeWorkspaceRoot(currentCwdCandidate) &&
4401
+ canTrustProcessCwdForClient(sessionClientName)
4402
+ ) {
4378
4403
  sessionWorkspaceDir = currentCwdCandidate;
4379
- // VS Code forks (Antigravity, Cursor) set cwd to workspace folder
4380
- // when spawning MCP server processes, so treat plausible cwd as trusted.
4404
+ // For selected clients, process cwd is a valid workspace signal.
4381
4405
  sessionWorkspaceTrusted = true;
4382
4406
  }
4383
4407
  }
@@ -4388,9 +4412,12 @@ async function runProxy(flags) {
4388
4412
  }
4389
4413
  }
4390
4414
  }
4415
+ const hasWeakRequestWorkspaceSignal =
4416
+ Boolean(weakRequestWorkspaceCandidate) && !isHomeWorkspaceRoot(weakRequestWorkspaceCandidate);
4391
4417
  const workspaceSignalTrusted =
4392
4418
  args.explicitPinnedWorkspace ||
4393
4419
  sessionWorkspaceTrusted ||
4420
+ hasWeakRequestWorkspaceSignal ||
4394
4421
  Boolean(strongRequestWorkspaceCandidate || strongEnvWorkspaceCandidate);
4395
4422
  const requestWorkspaceDir = args.explicitPinnedWorkspace
4396
4423
  ? resolveWorkspaceDir(args.workspaceDir || process.cwd())
@@ -5149,13 +5176,9 @@ function runSetupInternal(flags, options = {}) {
5149
5176
  const transport = getRegisteredTransport(cliBin, context.serverName);
5150
5177
  if (transport) {
5151
5178
  const existingWorkspaceDir = extractWorkspaceDirArg(transport.args);
5152
- const existingEnv = safeObject(transport.env);
5153
- const existingWorkspaceEnv = String(existingEnv.METHEUS_WORKSPACE_DIR || "").trim();
5154
5179
  if (existingWorkspaceDir && !isAutoWorkspaceMode(existingWorkspaceDir)) {
5155
5180
  proxyArgsForRegister = withWorkspaceDirArg(proxyArgsForRegister, existingWorkspaceDir);
5156
5181
  workspaceEnvForRegister = "";
5157
- } else if (!workspaceEnvForRegister && existingWorkspaceEnv) {
5158
- workspaceEnvForRegister = resolveWorkspaceDir(existingWorkspaceEnv);
5159
5182
  }
5160
5183
  }
5161
5184
  }
@@ -5266,10 +5289,21 @@ function runSelftest(flags = {}) {
5266
5289
  const originalWorkspaceEnv = process.env.METHEUS_WORKSPACE_DIR;
5267
5290
  const forcedEnvWorkspace = path.join(tempRoot, "forced-workspace");
5268
5291
  const defaultWorkspace = path.join(tempRoot, "default-workspace");
5292
+ const weakRequestWorkspace = path.join(tempRoot, "weak-request-workspace");
5269
5293
  fs.mkdirSync(forcedEnvWorkspace, { recursive: true });
5270
5294
  fs.mkdirSync(defaultWorkspace, { recursive: true });
5295
+ fs.mkdirSync(weakRequestWorkspace, { recursive: true });
5271
5296
  process.env.METHEUS_WORKSPACE_DIR = forcedEnvWorkspace;
5272
5297
  const resolvedByEnvPriority = resolveWorkspaceDirForRequest(defaultWorkspace, {}, {});
5298
+ const resolvedByWeakRequestPriority = resolveWorkspaceDirForRequest(
5299
+ defaultWorkspace,
5300
+ {
5301
+ params: {
5302
+ cwd: weakRequestWorkspace,
5303
+ },
5304
+ },
5305
+ {},
5306
+ );
5273
5307
  if (typeof originalWorkspaceEnv === "string") {
5274
5308
  process.env.METHEUS_WORKSPACE_DIR = originalWorkspaceEnv;
5275
5309
  } else {
@@ -5282,6 +5316,13 @@ function runSelftest(flags = {}) {
5282
5316
  envPriorityOk,
5283
5317
  `env=${forcedEnvWorkspace} default=${defaultWorkspace} resolved=${resolvedByEnvPriority || "(none)"}`,
5284
5318
  );
5319
+ const weakRequestPriorityOk =
5320
+ normalizedPathForCompare(resolvedByWeakRequestPriority) === normalizedPathForCompare(weakRequestWorkspace);
5321
+ push(
5322
+ "workspace_weak_request_priority_over_env",
5323
+ weakRequestPriorityOk,
5324
+ `request=${weakRequestWorkspace} env=${forcedEnvWorkspace} resolved=${resolvedByWeakRequestPriority || "(none)"}`,
5325
+ );
5285
5326
  } catch (err) {
5286
5327
  push("workspace_env_guard_test_setup", false, String(err?.message || err));
5287
5328
  } finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metheus-governance-mcp-cli",
3
- "version": "0.2.42",
3
+ "version": "0.2.44",
4
4
  "description": "Metheus Governance MCP CLI (setup + stdio proxy)",
5
5
  "type": "module",
6
6
  "files": [