@bryan-thompson/inspector-assessment 1.35.3 → 1.36.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.
- package/cli/build/__tests__/assess-full-e2e.test.js +12 -2
- package/cli/build/__tests__/assess-full.test.js +1 -1
- package/cli/build/__tests__/assessment-runner/assessment-executor.test.js +1 -1
- package/cli/build/__tests__/assessment-runner/index.test.js +6 -4
- package/cli/build/__tests__/assessment-runner/path-resolver.test.js +112 -0
- package/cli/build/__tests__/assessment-runner/source-loader.test.js +92 -0
- package/cli/build/__tests__/assessment-runner-facade.test.js +4 -2
- package/cli/build/__tests__/cli-build-fixes.test.js +1 -1
- package/cli/build/__tests__/http-transport-integration.test.js +9 -2
- package/cli/build/__tests__/jsonl-events.test.js +1 -1
- package/cli/build/__tests__/security/security-pattern-count.test.js +3 -3
- package/cli/build/__tests__/stage3-fix-validation.test.js +1 -1
- package/cli/build/__tests__/testbed-integration.test.js +9 -2
- package/cli/build/__tests__/transport.test.js +1 -1
- package/cli/build/lib/__tests__/cli-parserSchemas.test.js +1 -1
- package/cli/build/lib/assessment-runner/__tests__/server-configSchemas.test.js +1 -1
- package/cli/build/lib/assessment-runner/assessment-executor.js +23 -4
- package/cli/build/lib/assessment-runner/index.js +2 -0
- package/cli/build/lib/assessment-runner/path-resolver.js +48 -0
- package/cli/build/lib/assessment-runner/source-loader.js +47 -5
- package/cli/build/lib/cli-parser.js +10 -0
- package/cli/package.json +1 -1
- package/client/dist/assets/{OAuthCallback-BglPlsRX.js → OAuthCallback-DHYVVs-U.js} +1 -1
- package/client/dist/assets/{OAuthDebugCallback-CWrUH2KB.js → OAuthDebugCallback-BrarwoAx.js} +1 -1
- package/client/dist/assets/{index-iCeeS8vg.js → index-Dup6F6QC.js} +4 -4
- package/client/dist/index.html +1 -1
- package/client/lib/lib/assessment/extendedTypes.d.ts +4 -0
- package/client/lib/lib/assessment/extendedTypes.d.ts.map +1 -1
- package/client/lib/lib/assessment/jsonlEventSchemas.d.ts +4 -4
- package/client/lib/lib/assessment/resultTypes.d.ts +22 -0
- package/client/lib/lib/assessment/resultTypes.d.ts.map +1 -1
- package/client/lib/lib/moduleScoring.d.ts.map +1 -1
- package/client/lib/lib/moduleScoring.js +45 -2
- package/client/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts +1 -0
- package/client/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts.map +1 -1
- package/client/lib/services/assessment/modules/ErrorHandlingAssessor.js +103 -8
- package/client/lib/services/assessment/modules/ProhibitedLibrariesAssessor.d.ts +5 -0
- package/client/lib/services/assessment/modules/ProhibitedLibrariesAssessor.d.ts.map +1 -1
- package/client/lib/services/assessment/modules/ProhibitedLibrariesAssessor.js +29 -0
- package/client/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
- package/client/lib/services/assessment/modules/SecurityAssessor.js +13 -0
- package/client/lib/services/assessment/modules/annotations/AlignmentChecker.d.ts +7 -2
- package/client/lib/services/assessment/modules/annotations/AlignmentChecker.d.ts.map +1 -1
- package/client/lib/services/assessment/modules/annotations/AlignmentChecker.js +116 -18
- package/client/lib/services/assessment/modules/annotations/index.d.ts +1 -1
- package/client/lib/services/assessment/modules/annotations/index.d.ts.map +1 -1
- package/client/lib/services/assessment/modules/annotations/index.js +2 -1
- package/client/package.json +1 -1
- package/package.json +1 -1
- package/server/package.json +1 -1
|
@@ -6,13 +6,16 @@ import { BaseAssessor } from "./BaseAssessor.js";
|
|
|
6
6
|
import { createConcurrencyLimit } from "../lib/concurrencyLimit.js";
|
|
7
7
|
import { ExecutionArtifactDetector } from "./securityTests/ExecutionArtifactDetector.js";
|
|
8
8
|
import { SafeResponseDetector } from "./securityTests/SafeResponseDetector.js";
|
|
9
|
+
import { ErrorClassifier } from "./securityTests/ErrorClassifier.js";
|
|
9
10
|
export class ErrorHandlingAssessor extends BaseAssessor {
|
|
10
11
|
executionDetector;
|
|
11
12
|
safeResponseDetector;
|
|
13
|
+
errorClassifier;
|
|
12
14
|
constructor(config) {
|
|
13
15
|
super(config);
|
|
14
16
|
this.executionDetector = new ExecutionArtifactDetector();
|
|
15
17
|
this.safeResponseDetector = new SafeResponseDetector();
|
|
18
|
+
this.errorClassifier = new ErrorClassifier();
|
|
16
19
|
}
|
|
17
20
|
async assess(context) {
|
|
18
21
|
this.logger.info("Starting error handling assessment");
|
|
@@ -56,6 +59,15 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
56
59
|
passedTests += toolTests.filter((t) => t.passed).length;
|
|
57
60
|
}
|
|
58
61
|
this.testCount = testDetails.length;
|
|
62
|
+
// Issue #153: Calculate test execution metadata for score validation
|
|
63
|
+
// Count connection errors from test results (tests with isConnectionError flag)
|
|
64
|
+
const connectionErrorTests = testDetails.filter((t) => t.isConnectionError);
|
|
65
|
+
const connectionErrorCount = connectionErrorTests.length;
|
|
66
|
+
const validTestsCompleted = testDetails.length - connectionErrorCount;
|
|
67
|
+
const totalTestsAttempted = testDetails.length;
|
|
68
|
+
const testCoveragePercent = totalTestsAttempted > 0
|
|
69
|
+
? Math.round((validTestsCompleted / totalTestsAttempted) * 100)
|
|
70
|
+
: 0;
|
|
59
71
|
const metrics = this.calculateMetrics(testDetails, passedTests);
|
|
60
72
|
const status = this.determineErrorHandlingStatus(metrics, testDetails.length);
|
|
61
73
|
const explanation = this.generateExplanation(metrics, testDetails);
|
|
@@ -68,6 +80,13 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
68
80
|
score: Math.round(metrics.mcpComplianceScore),
|
|
69
81
|
explanation,
|
|
70
82
|
recommendations,
|
|
83
|
+
// Issue #153: Test execution metadata for score validation
|
|
84
|
+
testExecutionMetadata: {
|
|
85
|
+
totalTestsAttempted,
|
|
86
|
+
validTestsCompleted,
|
|
87
|
+
connectionErrorCount,
|
|
88
|
+
testCoveragePercent,
|
|
89
|
+
},
|
|
71
90
|
};
|
|
72
91
|
}
|
|
73
92
|
selectToolsForTesting(tools) {
|
|
@@ -175,6 +194,25 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
175
194
|
};
|
|
176
195
|
}
|
|
177
196
|
catch (error) {
|
|
197
|
+
// Issue #153: Check for connection errors first - these should NOT count as passed
|
|
198
|
+
if (this.errorClassifier.isConnectionErrorFromException(error)) {
|
|
199
|
+
const errorInfo = this.extractErrorInfo(error);
|
|
200
|
+
return {
|
|
201
|
+
toolName: tool.name,
|
|
202
|
+
testType: "missing_required",
|
|
203
|
+
testInput,
|
|
204
|
+
expectedError: "Missing required parameters",
|
|
205
|
+
actualResponse: {
|
|
206
|
+
isError: true,
|
|
207
|
+
errorCode: errorInfo.code,
|
|
208
|
+
errorMessage: errorInfo.message,
|
|
209
|
+
rawResponse: error,
|
|
210
|
+
},
|
|
211
|
+
passed: false,
|
|
212
|
+
reason: "Connection error - unable to test",
|
|
213
|
+
isConnectionError: true,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
178
216
|
// Check if the error message is meaningful (not just a generic crash)
|
|
179
217
|
const errorInfo = this.extractErrorInfo(error);
|
|
180
218
|
const messageLower = errorInfo.message?.toLowerCase() ?? "";
|
|
@@ -183,8 +221,8 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
183
221
|
messageLower.includes("parameter") ||
|
|
184
222
|
messageLower.includes("must") ||
|
|
185
223
|
messageLower.includes("invalid") ||
|
|
186
|
-
messageLower.includes("validation")
|
|
187
|
-
|
|
224
|
+
messageLower.includes("validation");
|
|
225
|
+
// Removed: (errorInfo.message?.length ?? 0) > 20 - this was causing false positives
|
|
188
226
|
return {
|
|
189
227
|
toolName: tool.name,
|
|
190
228
|
testType: "missing_required",
|
|
@@ -242,6 +280,25 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
242
280
|
};
|
|
243
281
|
}
|
|
244
282
|
catch (error) {
|
|
283
|
+
// Issue #153: Check for connection errors first - these should NOT count as passed
|
|
284
|
+
if (this.errorClassifier.isConnectionErrorFromException(error)) {
|
|
285
|
+
const errorInfo = this.extractErrorInfo(error);
|
|
286
|
+
return {
|
|
287
|
+
toolName: tool.name,
|
|
288
|
+
testType: "wrong_type",
|
|
289
|
+
testInput,
|
|
290
|
+
expectedError: "Type validation error",
|
|
291
|
+
actualResponse: {
|
|
292
|
+
isError: true,
|
|
293
|
+
errorCode: errorInfo.code,
|
|
294
|
+
errorMessage: errorInfo.message,
|
|
295
|
+
rawResponse: error,
|
|
296
|
+
},
|
|
297
|
+
passed: false,
|
|
298
|
+
reason: "Connection error - unable to test",
|
|
299
|
+
isConnectionError: true,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
245
302
|
// Check if the error message is meaningful (not just a generic crash)
|
|
246
303
|
const errorInfo = this.extractErrorInfo(error);
|
|
247
304
|
const messageLower = errorInfo.message?.toLowerCase() ?? "";
|
|
@@ -251,8 +308,8 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
251
308
|
messageLower.includes("must be") ||
|
|
252
309
|
messageLower.includes("validation") ||
|
|
253
310
|
messageLower.includes("string") ||
|
|
254
|
-
messageLower.includes("number")
|
|
255
|
-
|
|
311
|
+
messageLower.includes("number");
|
|
312
|
+
// Removed: (errorInfo.message?.length ?? 0) > 20 - this was causing false positives
|
|
256
313
|
return {
|
|
257
314
|
toolName: tool.name,
|
|
258
315
|
testType: "wrong_type",
|
|
@@ -294,6 +351,25 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
294
351
|
};
|
|
295
352
|
}
|
|
296
353
|
catch (error) {
|
|
354
|
+
// Issue #153: Check for connection errors first - these should NOT count as passed
|
|
355
|
+
if (this.errorClassifier.isConnectionErrorFromException(error)) {
|
|
356
|
+
const errorInfo = this.extractErrorInfo(error);
|
|
357
|
+
return {
|
|
358
|
+
toolName: tool.name,
|
|
359
|
+
testType: "invalid_values",
|
|
360
|
+
testInput,
|
|
361
|
+
expectedError: "Invalid parameter values",
|
|
362
|
+
actualResponse: {
|
|
363
|
+
isError: true,
|
|
364
|
+
errorCode: errorInfo.code,
|
|
365
|
+
errorMessage: errorInfo.message,
|
|
366
|
+
rawResponse: error,
|
|
367
|
+
},
|
|
368
|
+
passed: false,
|
|
369
|
+
reason: "Connection error - unable to test",
|
|
370
|
+
isConnectionError: true,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
297
373
|
// Check if the error message is meaningful (not just a generic crash)
|
|
298
374
|
const errorInfo = this.extractErrorInfo(error);
|
|
299
375
|
const messageLower = errorInfo.message?.toLowerCase() ?? "";
|
|
@@ -302,8 +378,8 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
302
378
|
messageLower.includes("must") ||
|
|
303
379
|
messageLower.includes("cannot") ||
|
|
304
380
|
messageLower.includes("validation") ||
|
|
305
|
-
messageLower.includes("error")
|
|
306
|
-
|
|
381
|
+
messageLower.includes("error");
|
|
382
|
+
// Removed: (errorInfo.message?.length ?? 0) > 15 - this was causing false positives
|
|
307
383
|
return {
|
|
308
384
|
toolName: tool.name,
|
|
309
385
|
testType: "invalid_values",
|
|
@@ -343,6 +419,25 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
343
419
|
};
|
|
344
420
|
}
|
|
345
421
|
catch (error) {
|
|
422
|
+
// Issue #153: Check for connection errors first - these should NOT count as passed
|
|
423
|
+
if (this.errorClassifier.isConnectionErrorFromException(error)) {
|
|
424
|
+
const errorInfo = this.extractErrorInfo(error);
|
|
425
|
+
return {
|
|
426
|
+
toolName: tool.name,
|
|
427
|
+
testType: "excessive_input",
|
|
428
|
+
testInput: { value: "[100KB string]" },
|
|
429
|
+
expectedError: "Input size limit exceeded",
|
|
430
|
+
actualResponse: {
|
|
431
|
+
isError: true,
|
|
432
|
+
errorCode: errorInfo.code,
|
|
433
|
+
errorMessage: errorInfo.message,
|
|
434
|
+
rawResponse: "[error details omitted]",
|
|
435
|
+
},
|
|
436
|
+
passed: false,
|
|
437
|
+
reason: "Connection error - unable to test",
|
|
438
|
+
isConnectionError: true,
|
|
439
|
+
};
|
|
440
|
+
}
|
|
346
441
|
// Check if the error message is meaningful (not just a generic crash)
|
|
347
442
|
const errorInfo = this.extractErrorInfo(error);
|
|
348
443
|
const messageLower = errorInfo.message?.toLowerCase() ?? "";
|
|
@@ -351,8 +446,8 @@ export class ErrorHandlingAssessor extends BaseAssessor {
|
|
|
351
446
|
messageLower.includes("limit") ||
|
|
352
447
|
messageLower.includes("exceed") ||
|
|
353
448
|
messageLower.includes("too") ||
|
|
354
|
-
messageLower.includes("maximum")
|
|
355
|
-
|
|
449
|
+
messageLower.includes("maximum");
|
|
450
|
+
// Removed: (errorInfo.message?.length ?? 0) > 10 - this was causing false positives
|
|
356
451
|
return {
|
|
357
452
|
toolName: tool.name,
|
|
358
453
|
testType: "excessive_input",
|
|
@@ -17,6 +17,11 @@ export declare class ProhibitedLibrariesAssessor extends BaseAssessor {
|
|
|
17
17
|
* Run prohibited libraries assessment
|
|
18
18
|
*/
|
|
19
19
|
assess(context: AssessmentContext): Promise<ProhibitedLibrariesAssessment>;
|
|
20
|
+
/**
|
|
21
|
+
* Create result when no files are available to scan (Issue #154)
|
|
22
|
+
* Follows the pattern established by ConformanceAssessor
|
|
23
|
+
*/
|
|
24
|
+
private createSkippedResult;
|
|
20
25
|
/**
|
|
21
26
|
* Check if file is a source file worth scanning
|
|
22
27
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProhibitedLibrariesAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ProhibitedLibrariesAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EACV,6BAA6B,EAI9B,MAAM,uBAAuB,CAAC;AAS/B,qBAAa,2BAA4B,SAAQ,YAAY;IAC3D;;OAEG;IACG,MAAM,CACV,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"ProhibitedLibrariesAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ProhibitedLibrariesAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EACV,6BAA6B,EAI9B,MAAM,uBAAuB,CAAC;AAS/B,qBAAa,2BAA4B,SAAQ,YAAY;IAC3D;;OAEG;IACG,MAAM,CACV,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,6BAA6B,CAAC;IAkLzC;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,YAAY;IA0BpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAqB1B;;;;;;;OAOG;IACH,OAAO,CAAC,0BAA0B;IAiClC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAoD3B;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;CA2EhC"}
|
|
@@ -18,6 +18,15 @@ export class ProhibitedLibrariesAssessor extends BaseAssessor {
|
|
|
18
18
|
async assess(context) {
|
|
19
19
|
this.logger.info("Starting prohibited libraries assessment");
|
|
20
20
|
this.testCount = 0;
|
|
21
|
+
// Issue #154: Check if there are any files to scan
|
|
22
|
+
const hasPackageJson = Boolean(context.packageJson);
|
|
23
|
+
const hasSourceFiles = Boolean(context.sourceCodeFiles &&
|
|
24
|
+
context.config.enableSourceCodeAnalysis &&
|
|
25
|
+
context.sourceCodeFiles.size > 0);
|
|
26
|
+
if (!hasPackageJson && !hasSourceFiles) {
|
|
27
|
+
this.logger.info("No package.json or source files available, skipping assessment");
|
|
28
|
+
return this.createSkippedResult("No package.json or source files provided. Enable source code analysis with --source flag.");
|
|
29
|
+
}
|
|
21
30
|
const matches = [];
|
|
22
31
|
const scannedFiles = [];
|
|
23
32
|
let hasFinancialLibraries = false;
|
|
@@ -137,6 +146,26 @@ export class ProhibitedLibrariesAssessor extends BaseAssessor {
|
|
|
137
146
|
recommendations,
|
|
138
147
|
};
|
|
139
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Create result when no files are available to scan (Issue #154)
|
|
151
|
+
* Follows the pattern established by ConformanceAssessor
|
|
152
|
+
*/
|
|
153
|
+
createSkippedResult(reason) {
|
|
154
|
+
return {
|
|
155
|
+
matches: [],
|
|
156
|
+
scannedFiles: [],
|
|
157
|
+
hasFinancialLibraries: false,
|
|
158
|
+
hasMediaLibraries: false,
|
|
159
|
+
status: "NEED_MORE_INFO",
|
|
160
|
+
explanation: `Prohibited libraries assessment skipped: ${reason}`,
|
|
161
|
+
recommendations: [
|
|
162
|
+
"Provide --source <path> to enable package.json and source file scanning",
|
|
163
|
+
"Ensure the source path exists and contains package.json or source files",
|
|
164
|
+
],
|
|
165
|
+
skipped: true,
|
|
166
|
+
skipReason: reason,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
140
169
|
/**
|
|
141
170
|
* Check if file is a source file worth scanning
|
|
142
171
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecurityAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/SecurityAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EACL,kBAAkB,EAInB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAiB9D,OAAO,EACL,gBAAgB,EAGjB,MAAM,yBAAyB,CAAC;AAEjC,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,YAAY,CAAiC;IAErD;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI;IAStD;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAOjC;;;OAGG;YACW,0BAA0B;gBAwBtC,MAAM,EAAE,OAAO,8BAA8B,EAAE,uBAAuB;IAwClE,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"SecurityAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/SecurityAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EACL,kBAAkB,EAInB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAiB9D,OAAO,EACL,gBAAgB,EAGjB,MAAM,yBAAyB,CAAC;AAEjC,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,YAAY,CAAiC;IAErD;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI;IAStD;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAOjC;;;OAGG;YACW,0BAA0B;gBAwBtC,MAAM,EAAE,OAAO,8BAA8B,EAAE,uBAAuB;IAwClE,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA8PrE;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAoC7B;;OAEG;YACW,+BAA+B;IAiC7C;;;OAGG;YACW,yBAAyB;IA0CvC;;;;;;;OAOG;YACW,yBAAyB;IAmFvC;;OAEG;IACH,OAAO,CAAC,yBAAyB;IAYjC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA0B/B;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAkEnC;;;OAGG;IACH,OAAO,CAAC,0BAA0B;CAgDnC"}
|
|
@@ -253,6 +253,12 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
253
253
|
}
|
|
254
254
|
// Issue #75: Aggregate auth bypass detection results
|
|
255
255
|
const authBypassSummary = this.aggregateAuthBypassResults(allTests);
|
|
256
|
+
// Issue #152: Calculate test execution metadata for score validation
|
|
257
|
+
const totalTestsAttempted = allTests.length;
|
|
258
|
+
const validTestsCompleted = validTests.length;
|
|
259
|
+
const testCoveragePercent = totalTestsAttempted > 0
|
|
260
|
+
? Math.round((validTestsCompleted / totalTestsAttempted) * 100)
|
|
261
|
+
: 0;
|
|
256
262
|
return {
|
|
257
263
|
promptInjectionTests: allTests,
|
|
258
264
|
vulnerabilities,
|
|
@@ -263,6 +269,13 @@ export class SecurityAssessor extends BaseAssessor {
|
|
|
263
269
|
// Issue #134: Test validity warning for response uniformity detection
|
|
264
270
|
testValidityWarning: validityResult.warning,
|
|
265
271
|
overallConfidence,
|
|
272
|
+
// Issue #152: Test execution metadata for score validation
|
|
273
|
+
testExecutionMetadata: {
|
|
274
|
+
totalTestsAttempted,
|
|
275
|
+
validTestsCompleted,
|
|
276
|
+
connectionErrorCount: connectionErrors.length,
|
|
277
|
+
testCoveragePercent,
|
|
278
|
+
},
|
|
266
279
|
};
|
|
267
280
|
}
|
|
268
281
|
/**
|
|
@@ -38,9 +38,14 @@ export interface AlignmentMetricsResult {
|
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
41
|
+
* Enable or disable annotation debug logging (Issue #155)
|
|
42
|
+
* Called by CLI when --debug-annotations flag is provided
|
|
43
43
|
*/
|
|
44
|
+
export declare function setAnnotationDebugMode(enabled: boolean): void;
|
|
45
|
+
/**
|
|
46
|
+
* Check if annotation debug mode is enabled
|
|
47
|
+
*/
|
|
48
|
+
export declare function isAnnotationDebugEnabled(): boolean;
|
|
44
49
|
export declare function extractAnnotations(tool: Tool): ExtractedAnnotations;
|
|
45
50
|
/**
|
|
46
51
|
* Extract extended metadata from tool (Issue #54)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlignmentChecker.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/annotations/AlignmentChecker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,EACV,oBAAoB,EACpB,gBAAgB,EAEhB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"AlignmentChecker.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/annotations/AlignmentChecker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,EACV,oBAAoB,EACpB,gBAAgB,EAEhB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EACV,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,gCAAgC,CAAC;AAuFxC;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;IACF,kBAAkB,EAAE;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AA0CD;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAE7D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAElD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,oBAAoB,CAiNnE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,IAAI,GACT,oBAAoB,CAAC,kBAAkB,CAAC,CA6D1C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,iBAAiB,EAAE,CAqBtE;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,IAAI,GAAG,mBAAmB,CAmD3E;AAqCD;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,gBAAgB,EAAE,gBAAgB,EAClC,kBAAkB,CAAC,EAAE,wBAAwB,GAC5C,oBAAoB,CA0JtB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,oBAAoB,EAAE,EAC/B,UAAU,EAAE,MAAM,GACjB,gBAAgB,CA8BlB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,oBAAoB,EAAE,EAC/B,UAAU,EAAE,MAAM,GACjB,sBAAsB,CA2BxB"}
|
|
@@ -7,57 +7,155 @@
|
|
|
7
7
|
import { scanDescriptionForPoisoning, } from "./DescriptionPoisoningDetector.js";
|
|
8
8
|
import { detectAnnotationDeception, isActionableConfidence, } from "./AnnotationDeceptionDetector.js";
|
|
9
9
|
import { inferBehavior } from "./BehaviorInference.js";
|
|
10
|
+
/**
|
|
11
|
+
* Helper to resolve annotation value with fallback (Issue #150)
|
|
12
|
+
* Checks *Hint suffix first (MCP spec), then non-suffixed version as fallback
|
|
13
|
+
* This handles servers that use 'readOnly' instead of 'readOnlyHint'
|
|
14
|
+
*
|
|
15
|
+
* @param obj - The object to search for annotation properties
|
|
16
|
+
* @param hintKey - The MCP spec compliant key (e.g., 'readOnlyHint')
|
|
17
|
+
* @param fallbackKey - The non-suffixed fallback key (e.g., 'readOnly')
|
|
18
|
+
* @returns The boolean annotation value, or undefined if not found or not a boolean
|
|
19
|
+
*/
|
|
20
|
+
function resolveAnnotationValue(obj, hintKey, fallbackKey) {
|
|
21
|
+
if (!obj)
|
|
22
|
+
return undefined;
|
|
23
|
+
// Priority: *Hint version (MCP spec)
|
|
24
|
+
if (obj[hintKey] !== undefined) {
|
|
25
|
+
const val = obj[hintKey];
|
|
26
|
+
if (typeof val === "boolean")
|
|
27
|
+
return val;
|
|
28
|
+
}
|
|
29
|
+
// Fallback: non-suffixed version (Issue #150)
|
|
30
|
+
if (obj[fallbackKey] !== undefined) {
|
|
31
|
+
const val = obj[fallbackKey];
|
|
32
|
+
if (typeof val === "boolean")
|
|
33
|
+
return val;
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
10
37
|
/**
|
|
11
38
|
* Extract annotations from a tool
|
|
12
39
|
* Checks multiple sources in priority order: annotations object, direct properties, metadata
|
|
40
|
+
* Issue #150: Also checks non-suffixed property names (readOnly, destructive) as fallback
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* Global debug flag for annotation extraction (Issue #155)
|
|
44
|
+
* Set via setAnnotationDebugMode() when --debug-annotations flag is used
|
|
45
|
+
*/
|
|
46
|
+
let annotationDebugMode = false;
|
|
47
|
+
/**
|
|
48
|
+
* Enable or disable annotation debug logging (Issue #155)
|
|
49
|
+
* Called by CLI when --debug-annotations flag is provided
|
|
50
|
+
*/
|
|
51
|
+
export function setAnnotationDebugMode(enabled) {
|
|
52
|
+
annotationDebugMode = enabled;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Check if annotation debug mode is enabled
|
|
13
56
|
*/
|
|
57
|
+
export function isAnnotationDebugEnabled() {
|
|
58
|
+
return annotationDebugMode;
|
|
59
|
+
}
|
|
14
60
|
export function extractAnnotations(tool) {
|
|
15
61
|
const extendedTool = tool;
|
|
62
|
+
// Issue #155: Debug logging when --debug-annotations flag is enabled
|
|
63
|
+
if (annotationDebugMode) {
|
|
64
|
+
console.log("[DEBUG-ANNOTATIONS]", tool.name, "| keys:", Object.keys(tool), "| annotations:", JSON.stringify(extendedTool.annotations), "| direct.readOnlyHint:", extendedTool.readOnlyHint);
|
|
65
|
+
}
|
|
16
66
|
// Priority 1: Check annotations object (MCP 2024-11 spec)
|
|
67
|
+
// Issue #150: Use resolveAnnotationValue to check both *Hint and non-suffixed versions
|
|
17
68
|
if (extendedTool.annotations) {
|
|
18
|
-
const
|
|
19
|
-
|
|
69
|
+
const annotationsObj = extendedTool.annotations;
|
|
70
|
+
const readOnlyValue = resolveAnnotationValue(annotationsObj, "readOnlyHint", "readOnly");
|
|
71
|
+
const destructiveValue = resolveAnnotationValue(annotationsObj, "destructiveHint", "destructive");
|
|
72
|
+
const hasAnnotations = readOnlyValue !== undefined || destructiveValue !== undefined;
|
|
20
73
|
if (hasAnnotations) {
|
|
21
74
|
return {
|
|
22
|
-
readOnlyHint:
|
|
23
|
-
destructiveHint:
|
|
75
|
+
readOnlyHint: readOnlyValue,
|
|
76
|
+
destructiveHint: destructiveValue,
|
|
24
77
|
title: extendedTool.annotations.title || extendedTool.title,
|
|
25
78
|
description: tool.description,
|
|
26
|
-
idempotentHint:
|
|
27
|
-
openWorldHint:
|
|
79
|
+
idempotentHint: resolveAnnotationValue(annotationsObj, "idempotentHint", "idempotent"),
|
|
80
|
+
openWorldHint: resolveAnnotationValue(annotationsObj, "openWorldHint", "openWorld"),
|
|
28
81
|
source: "mcp",
|
|
29
82
|
};
|
|
30
83
|
}
|
|
31
84
|
}
|
|
32
85
|
// Priority 2: Check direct properties
|
|
33
|
-
|
|
34
|
-
|
|
86
|
+
// Issue #150: Use resolveAnnotationValue to check both *Hint and non-suffixed versions
|
|
87
|
+
const directObj = extendedTool;
|
|
88
|
+
const directReadOnly = resolveAnnotationValue(directObj, "readOnlyHint", "readOnly");
|
|
89
|
+
const directDestructive = resolveAnnotationValue(directObj, "destructiveHint", "destructive");
|
|
90
|
+
if (directReadOnly !== undefined || directDestructive !== undefined) {
|
|
35
91
|
return {
|
|
36
|
-
readOnlyHint:
|
|
37
|
-
destructiveHint:
|
|
92
|
+
readOnlyHint: directReadOnly,
|
|
93
|
+
destructiveHint: directDestructive,
|
|
38
94
|
title: extendedTool.title,
|
|
39
95
|
description: tool.description,
|
|
40
|
-
idempotentHint:
|
|
41
|
-
openWorldHint:
|
|
96
|
+
idempotentHint: resolveAnnotationValue(directObj, "idempotentHint", "idempotent"),
|
|
97
|
+
openWorldHint: resolveAnnotationValue(directObj, "openWorldHint", "openWorld"),
|
|
42
98
|
source: "mcp",
|
|
43
99
|
};
|
|
44
100
|
}
|
|
45
101
|
// Priority 3: Check metadata
|
|
102
|
+
// Issue #150: Use resolveAnnotationValue to check both *Hint and non-suffixed versions
|
|
46
103
|
if (extendedTool.metadata) {
|
|
47
|
-
const
|
|
48
|
-
|
|
104
|
+
const metadataObj = extendedTool.metadata;
|
|
105
|
+
const metaReadOnly = resolveAnnotationValue(metadataObj, "readOnlyHint", "readOnly");
|
|
106
|
+
const metaDestructive = resolveAnnotationValue(metadataObj, "destructiveHint", "destructive");
|
|
107
|
+
const hasMetadataAnnotations = metaReadOnly !== undefined || metaDestructive !== undefined;
|
|
49
108
|
if (hasMetadataAnnotations) {
|
|
50
109
|
return {
|
|
51
|
-
readOnlyHint:
|
|
52
|
-
destructiveHint:
|
|
110
|
+
readOnlyHint: metaReadOnly,
|
|
111
|
+
destructiveHint: metaDestructive,
|
|
53
112
|
title: extendedTool.metadata.title || extendedTool.title,
|
|
54
113
|
description: tool.description,
|
|
55
|
-
idempotentHint:
|
|
56
|
-
openWorldHint:
|
|
114
|
+
idempotentHint: resolveAnnotationValue(metadataObj, "idempotentHint", "idempotent"),
|
|
115
|
+
openWorldHint: resolveAnnotationValue(metadataObj, "openWorldHint", "openWorld"),
|
|
116
|
+
source: "mcp",
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Priority 4: Check _meta object (MCP spec allows arbitrary data here)
|
|
121
|
+
// Issue #155: Some servers may store annotations in _meta
|
|
122
|
+
if (extendedTool._meta) {
|
|
123
|
+
const metaObj = extendedTool._meta;
|
|
124
|
+
const metaReadOnly = resolveAnnotationValue(metaObj, "readOnlyHint", "readOnly");
|
|
125
|
+
const metaDestructive = resolveAnnotationValue(metaObj, "destructiveHint", "destructive");
|
|
126
|
+
if (metaReadOnly !== undefined || metaDestructive !== undefined) {
|
|
127
|
+
return {
|
|
128
|
+
readOnlyHint: metaReadOnly,
|
|
129
|
+
destructiveHint: metaDestructive,
|
|
130
|
+
title: metaObj.title,
|
|
131
|
+
description: tool.description,
|
|
132
|
+
idempotentHint: resolveAnnotationValue(metaObj, "idempotentHint", "idempotent"),
|
|
133
|
+
openWorldHint: resolveAnnotationValue(metaObj, "openWorldHint", "openWorld"),
|
|
57
134
|
source: "mcp",
|
|
58
135
|
};
|
|
59
136
|
}
|
|
60
137
|
}
|
|
138
|
+
// Priority 5: Check annotations.hints (nested structure some servers use)
|
|
139
|
+
// Issue #155: Handle servers that nest hints inside annotations object
|
|
140
|
+
if (extendedTool.annotations) {
|
|
141
|
+
const hintsObj = extendedTool.annotations
|
|
142
|
+
.hints;
|
|
143
|
+
if (hintsObj) {
|
|
144
|
+
const hintsReadOnly = resolveAnnotationValue(hintsObj, "readOnlyHint", "readOnly");
|
|
145
|
+
const hintsDestructive = resolveAnnotationValue(hintsObj, "destructiveHint", "destructive");
|
|
146
|
+
if (hintsReadOnly !== undefined || hintsDestructive !== undefined) {
|
|
147
|
+
return {
|
|
148
|
+
readOnlyHint: hintsReadOnly,
|
|
149
|
+
destructiveHint: hintsDestructive,
|
|
150
|
+
title: extendedTool.annotations.title,
|
|
151
|
+
description: tool.description,
|
|
152
|
+
idempotentHint: resolveAnnotationValue(hintsObj, "idempotentHint", "idempotent"),
|
|
153
|
+
openWorldHint: resolveAnnotationValue(hintsObj, "openWorldHint", "openWorld"),
|
|
154
|
+
source: "mcp",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
61
159
|
return {
|
|
62
160
|
title: extendedTool.title,
|
|
63
161
|
description: tool.description,
|
|
@@ -16,7 +16,7 @@ export { analyzeDescription, hasReadOnlyIndicators, hasDestructiveIndicators, ha
|
|
|
16
16
|
export { analyzeInputSchema, analyzeOutputSchema, hasBulkOperationIndicators, hasPaginationParameters, hasForceFlags, INPUT_READONLY_PATTERNS, INPUT_DESTRUCTIVE_PATTERNS, INPUT_WRITE_PATTERNS, OUTPUT_READONLY_PATTERNS, OUTPUT_DESTRUCTIVE_PATTERNS, OUTPUT_WRITE_PATTERNS, type JSONSchema, } from "./SchemaAnalyzer.js";
|
|
17
17
|
export { detectArchitecture, hasDatabaseToolPatterns, extractDatabasesFromDependencies, type Tool as ArchitectureTool, type ArchitectureContext, } from "./ArchitectureDetector.js";
|
|
18
18
|
export { type ClaudeInference, type EnhancedToolAnnotationResult, } from "./types.js";
|
|
19
|
-
export { extractAnnotations, extractExtendedMetadata, extractToolParams, scanInputSchemaDescriptions, assessSingleTool, determineAnnotationStatus, calculateMetrics, type ExtractedAnnotations, type AlignmentMetricsResult, } from "./AlignmentChecker.js";
|
|
19
|
+
export { extractAnnotations, extractExtendedMetadata, extractToolParams, scanInputSchemaDescriptions, assessSingleTool, determineAnnotationStatus, calculateMetrics, setAnnotationDebugMode, isAnnotationDebugEnabled, type ExtractedAnnotations, type AlignmentMetricsResult, } from "./AlignmentChecker.js";
|
|
20
20
|
export { generateExplanation, generateEnhancedExplanation, generateRecommendations, generateEnhancedRecommendations, } from "./ExplanationGenerator.js";
|
|
21
21
|
export { emitAnnotationEvents, emitMismatchEvent } from "./EventEmitter.js";
|
|
22
22
|
export { enhanceWithClaudeInference, createPatternBasedInference, } from "./ClaudeIntegration.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/annotations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,+BAA+B,EAC/B,4BAA4B,EAC5B,kCAAkC,EAClC,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,EACzB,KAAK,eAAe,GACrB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,aAAa,EACb,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,EACpB,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,KAAK,UAAU,GAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,gCAAgC,EAChC,KAAK,IAAI,IAAI,gBAAgB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,4BAA4B,GAClC,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/services/assessment/modules/annotations/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,+BAA+B,EAC/B,4BAA4B,EAC5B,kCAAkC,EAClC,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,EACzB,KAAK,eAAe,GACrB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,KAAK,uBAAuB,GAC7B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,EAClB,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,0BAA0B,EAC1B,uBAAuB,EACvB,aAAa,EACb,uBAAuB,EACvB,0BAA0B,EAC1B,oBAAoB,EACpB,wBAAwB,EACxB,2BAA2B,EAC3B,qBAAqB,EACrB,KAAK,UAAU,GAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,gCAAgC,EAChC,KAAK,IAAI,IAAI,gBAAgB,EAC7B,KAAK,mBAAmB,GACzB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,4BAA4B,GAClC,MAAM,SAAS,CAAC;AAKjB,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,gBAAgB,EAChB,yBAAyB,EACzB,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,EACxB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,+BAA+B,GAChC,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGzE,OAAO,EACL,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,qBAAqB,CAAC"}
|
|
@@ -20,7 +20,8 @@ export { analyzeInputSchema, analyzeOutputSchema, hasBulkOperationIndicators, ha
|
|
|
20
20
|
export { detectArchitecture, hasDatabaseToolPatterns, extractDatabasesFromDependencies, } from "./ArchitectureDetector.js";
|
|
21
21
|
// Issue #105: Alignment Checker
|
|
22
22
|
// Issue #119: Added scanInputSchemaDescriptions for Challenge #15
|
|
23
|
-
|
|
23
|
+
// Issue #155: Added setAnnotationDebugMode for debug logging
|
|
24
|
+
export { extractAnnotations, extractExtendedMetadata, extractToolParams, scanInputSchemaDescriptions, assessSingleTool, determineAnnotationStatus, calculateMetrics, setAnnotationDebugMode, isAnnotationDebugEnabled, } from "./AlignmentChecker.js";
|
|
24
25
|
// Issue #105: Explanation Generator
|
|
25
26
|
export { generateExplanation, generateEnhancedExplanation, generateRecommendations, generateEnhancedRecommendations, } from "./ExplanationGenerator.js";
|
|
26
27
|
// Issue #105: Event Emitter
|
package/client/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bryan-thompson/inspector-assessment-client",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.1",
|
|
4
4
|
"description": "Client-side application for the Enhanced MCP Inspector with assessment capabilities",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bryan Thompson <bryan@triepod.ai>",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bryan-thompson/inspector-assessment",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.1",
|
|
4
4
|
"description": "Enhanced MCP Inspector with comprehensive assessment capabilities for server validation",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bryan Thompson <bryan@triepod.ai>",
|
package/server/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bryan-thompson/inspector-assessment-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.36.1",
|
|
4
4
|
"description": "Server-side application for the Enhanced MCP Inspector with assessment capabilities",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Bryan Thompson <bryan@triepod.ai>",
|