mcp-proof 0.3.19 → 0.3.20
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 +12 -0
- package/bin/mcp-proof.js +11 -0
- package/engine.js +1 -1
- package/package.json +2 -2
- package/test.js +9 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.20
|
|
4
|
+
|
|
5
|
+
- **Fix: `--inspect-call` in the default (human-readable) mode crashed** with
|
|
6
|
+
`Cannot read properties of undefined (reading 'toFixed')` (exit 65) for every
|
|
7
|
+
input; only `--json` worked. It now prints a verdict and reasons and keeps the
|
|
8
|
+
exit codes (0 allow, 1 warn, 2 block).
|
|
9
|
+
- `--inspect-call` now accepts a plain `{"name": ..., "arguments": ...}` payload as well as
|
|
10
|
+
`{"tool": ...}` and JSON-RPC `{"params": {"name": ...}}`; previously `name` at the top
|
|
11
|
+
level gave an empty tool name.
|
|
12
|
+
- Two regression tests added (22 public checks). Decisions and scores for `tools/list`
|
|
13
|
+
scans are unchanged. `vetokernel-client.js` still does not ship (see 0.3.19).
|
|
14
|
+
|
|
3
15
|
## 0.3.19
|
|
4
16
|
|
|
5
17
|
Readiness hardening — closes the audit findings, keeps all decisions and
|
package/bin/mcp-proof.js
CHANGED
|
@@ -776,7 +776,18 @@ function renderMulti(output) {
|
|
|
776
776
|
process.stdout.write(` ${c.bold}Overall${c.reset} ${output.decision.toUpperCase()}\n\n`);
|
|
777
777
|
}
|
|
778
778
|
|
|
779
|
+
function renderInspectCall(r) {
|
|
780
|
+
const c = COLORS;
|
|
781
|
+
const color = r.decision === 'allow' ? c.green : r.decision === 'warn' ? c.yellow : c.red;
|
|
782
|
+
const lines = ['', ` ${c.bold}mcp-proof${c.reset} ${c.dim}— inspect-call${r.tool ? ` ${r.tool}` : ''}, ${r.durationMs || 0}ms${c.reset}`, '',
|
|
783
|
+
` Verdict ${color}${c.bold}${String(r.decision).toUpperCase()}${c.reset}`, '', ` ${c.bold}Why${c.reset}`];
|
|
784
|
+
for (const reason of r.reasons) lines.push(` - ${reason}`);
|
|
785
|
+
if (!r.reasons.length) lines.push(' - no runtime-payload patterns detected');
|
|
786
|
+
process.stdout.write(lines.join('\n') + '\n\n');
|
|
787
|
+
}
|
|
788
|
+
|
|
779
789
|
function renderHumanReadable(r, toolCount, label = '') {
|
|
790
|
+
if (r.mode === 'inspect-call') return renderInspectCall(r);
|
|
780
791
|
const c = COLORS;
|
|
781
792
|
const verdict = r.decision.toUpperCase();
|
|
782
793
|
const verdictColor = r.decision === 'allow' ? c.green : r.decision === 'warn' ? c.yellow : c.red;
|
package/engine.js
CHANGED
|
@@ -756,7 +756,7 @@ function scanCall(toolName, args) {
|
|
|
756
756
|
|
|
757
757
|
function evaluateCall(req) {
|
|
758
758
|
const start = Date.now();
|
|
759
|
-
const toolName = req.tool || (req.params && req.params.name) || '';
|
|
759
|
+
const toolName = req.tool || req.name || (req.params && req.params.name) || '';
|
|
760
760
|
const args = req.arguments || (req.params && req.params.arguments) || {};
|
|
761
761
|
const scan = scanCall(toolName, args);
|
|
762
762
|
const score = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-proof",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.20",
|
|
4
4
|
"description": "Auditable, privacy-preserving MCP (Model Context Protocol) server verifier with local Trust Cards and SARIF output — test servers before connecting them to an AI system.",
|
|
5
5
|
"main": "engine.js",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|
|
25
|
-
"test": "node test.js",
|
|
25
|
+
"test": "node test.js && node test-canonical.js",
|
|
26
26
|
"test:private": "node test-private.js",
|
|
27
27
|
"test:all": "node test.js && node test-private.js",
|
|
28
28
|
"campaign:validate": "node campaign/campaign-tools.js validate",
|
package/test.js
CHANGED
|
@@ -295,5 +295,14 @@ check(
|
|
|
295
295
|
`decision=${benignSkillResult.decision} ${JSON.stringify(benignSkillResult.toolPoisoning)}`,
|
|
296
296
|
);
|
|
297
297
|
|
|
298
|
+
// --inspect-call in human-readable mode must render (it used to crash on a missing TrustScore) and keep the block/allow exit codes.
|
|
299
|
+
for (const [label, call, wantStatus, wantText] of [
|
|
300
|
+
['blocked call', { name: 'read_file', arguments: { path: '~/.ssh/id_rsa' } }, 2, 'BLOCK'],
|
|
301
|
+
['clean call', { name: 'get_weather', arguments: { city: 'Paris' } }, 0, 'ALLOW'],
|
|
302
|
+
]) {
|
|
303
|
+
const r = require('child_process').spawnSync(process.execPath, [require('path').join(__dirname, 'bin', 'mcp-proof.js'), '--inspect-call'], { input: JSON.stringify(call), encoding: 'utf8' });
|
|
304
|
+
check(r.status === wantStatus && r.stdout.includes(wantText) && r.stdout.includes(call.name), `--inspect-call human output: ${label}`, `status=${r.status} stderr=${(r.stderr || '').slice(0, 80)}`);
|
|
305
|
+
}
|
|
306
|
+
|
|
298
307
|
console.log(`\n${pass}/${pass + fail} public tests passed`);
|
|
299
308
|
process.exit(fail === 0 ? 0 : 1);
|