metheus-governance-mcp-cli 0.2.7 → 0.2.9
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/cli.mjs +83 -14
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -168,9 +168,33 @@ function extractWorkspaceCandidateFromRequest(requestObj, toolArgs) {
|
|
|
168
168
|
return resolveWorkspaceDir(candidate);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
+
function extractWorkspaceCandidateFromEnv() {
|
|
172
|
+
const rawCandidate = firstNonEmptyString([
|
|
173
|
+
process.env.METHEUS_WORKSPACE_DIR,
|
|
174
|
+
process.env.CLAUDE_WORKSPACE_DIR,
|
|
175
|
+
process.env.CLAUDE_PROJECT_DIR,
|
|
176
|
+
process.env.CODEX_WORKSPACE_DIR,
|
|
177
|
+
process.env.WORKSPACE_DIR,
|
|
178
|
+
process.env.WORKSPACE_FOLDER,
|
|
179
|
+
process.env.VSCODE_CWD,
|
|
180
|
+
process.env.PWD,
|
|
181
|
+
process.env.INIT_CWD,
|
|
182
|
+
]);
|
|
183
|
+
const fileCandidate = fileURIToLocalPath(rawCandidate);
|
|
184
|
+
const candidate = firstNonEmptyString([fileCandidate, rawCandidate]);
|
|
185
|
+
if (!candidate) return "";
|
|
186
|
+
return resolveWorkspaceDir(candidate);
|
|
187
|
+
}
|
|
188
|
+
|
|
171
189
|
function resolveWorkspaceDirForRequest(defaultWorkspaceDir, requestObj, toolArgs) {
|
|
172
190
|
const requestCandidate = extractWorkspaceCandidateFromRequest(requestObj, toolArgs);
|
|
173
|
-
const
|
|
191
|
+
const envCandidate = extractWorkspaceCandidateFromEnv();
|
|
192
|
+
const candidate = firstNonEmptyString([
|
|
193
|
+
requestCandidate,
|
|
194
|
+
envCandidate,
|
|
195
|
+
defaultWorkspaceDir,
|
|
196
|
+
process.cwd(),
|
|
197
|
+
]);
|
|
174
198
|
return resolveWorkspaceDir(candidate);
|
|
175
199
|
}
|
|
176
200
|
|
|
@@ -1387,6 +1411,19 @@ function addDoctorCheck(rows, status, label, detail) {
|
|
|
1387
1411
|
});
|
|
1388
1412
|
}
|
|
1389
1413
|
|
|
1414
|
+
function isUnauthorizedLike(rawText) {
|
|
1415
|
+
const text = String(rawText || "").trim().toLowerCase();
|
|
1416
|
+
if (!text) return false;
|
|
1417
|
+
return (
|
|
1418
|
+
text.includes("unauthorized") ||
|
|
1419
|
+
text.includes("access denied") ||
|
|
1420
|
+
text.includes("status 401") ||
|
|
1421
|
+
text.includes("status 403") ||
|
|
1422
|
+
text.includes("http 401") ||
|
|
1423
|
+
text.includes("http 403")
|
|
1424
|
+
);
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1390
1427
|
function statusIcon(status) {
|
|
1391
1428
|
if (status === "ok") return "OK";
|
|
1392
1429
|
if (status === "fail") return "FAIL";
|
|
@@ -1671,12 +1708,25 @@ async function runDoctor(flags) {
|
|
|
1671
1708
|
addDoctorCheck(rows, "ok", "server mode", "ctxpack writable");
|
|
1672
1709
|
}
|
|
1673
1710
|
} catch (err) {
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1711
|
+
const statusCode = Number(err?.statusCode || 0);
|
|
1712
|
+
const message = String(err?.message || err);
|
|
1713
|
+
if (statusCode === 404) {
|
|
1714
|
+
addDoctorCheck(
|
|
1715
|
+
rows,
|
|
1716
|
+
"ok",
|
|
1717
|
+
"server ctxpack policy",
|
|
1718
|
+
"ctxpack/stats endpoint is not exposed in this deployment (optional check skipped)",
|
|
1719
|
+
);
|
|
1720
|
+
} else if (statusCode === 401 || statusCode === 403 || isUnauthorizedLike(message)) {
|
|
1721
|
+
addDoctorCheck(
|
|
1722
|
+
rows,
|
|
1723
|
+
"warn",
|
|
1724
|
+
"server ctxpack policy",
|
|
1725
|
+
"no permission to read ctxpack/stats in this environment",
|
|
1726
|
+
);
|
|
1727
|
+
} else {
|
|
1728
|
+
addDoctorCheck(rows, "warn", "server ctxpack policy", `unable to read /ctxpack/stats (${message})`);
|
|
1729
|
+
}
|
|
1680
1730
|
}
|
|
1681
1731
|
}
|
|
1682
1732
|
|
|
@@ -1712,7 +1762,17 @@ async function runDoctor(flags) {
|
|
|
1712
1762
|
},
|
|
1713
1763
|
});
|
|
1714
1764
|
if (!rpc.ok) {
|
|
1715
|
-
|
|
1765
|
+
const errorText = String(rpc.error || "rpc error");
|
|
1766
|
+
if (isUnauthorizedLike(errorText)) {
|
|
1767
|
+
addDoctorCheck(
|
|
1768
|
+
rows,
|
|
1769
|
+
"warn",
|
|
1770
|
+
`smoke ${row.tool}`,
|
|
1771
|
+
"unauthorized for this tool with current token/project role",
|
|
1772
|
+
);
|
|
1773
|
+
} else {
|
|
1774
|
+
addDoctorCheck(rows, "fail", `smoke ${row.tool}`, errorText);
|
|
1775
|
+
}
|
|
1716
1776
|
continue;
|
|
1717
1777
|
}
|
|
1718
1778
|
const envelope = parseToolEnvelopeFromRPCResult(safeObject(rpc.response).result);
|
|
@@ -1725,12 +1785,21 @@ async function runDoctor(flags) {
|
|
|
1725
1785
|
if (ok && status >= 200 && status < 300) {
|
|
1726
1786
|
addDoctorCheck(rows, "ok", `smoke ${row.tool}`, `status ${status}`);
|
|
1727
1787
|
} else {
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1788
|
+
if (status === 401 || status === 403) {
|
|
1789
|
+
addDoctorCheck(
|
|
1790
|
+
rows,
|
|
1791
|
+
"warn",
|
|
1792
|
+
`smoke ${row.tool}`,
|
|
1793
|
+
`status ${status}: unauthorized for this tool with current token/project role`,
|
|
1794
|
+
);
|
|
1795
|
+
} else {
|
|
1796
|
+
addDoctorCheck(
|
|
1797
|
+
rows,
|
|
1798
|
+
"fail",
|
|
1799
|
+
`smoke ${row.tool}`,
|
|
1800
|
+
`status ${status || "-"}, ok=${ok ? "true" : "false"}`,
|
|
1801
|
+
);
|
|
1802
|
+
}
|
|
1734
1803
|
}
|
|
1735
1804
|
}
|
|
1736
1805
|
|