@bryan-thompson/inspector-assessment 1.37.0 → 1.38.0

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 (80) hide show
  1. package/cli/build/lib/assessment-runner/assessment-executor.js +29 -1
  2. package/cli/build/lib/assessment-runner/source-loader.js +11 -0
  3. package/cli/package.json +1 -1
  4. package/client/dist/assets/{OAuthCallback-6-wM7Zc1.js → OAuthCallback-AngeBaCl.js} +1 -1
  5. package/client/dist/assets/{OAuthDebugCallback-Bw9-AzzP.js → OAuthDebugCallback--FE6_fPs.js} +1 -1
  6. package/client/dist/assets/{index-DyCdQP10.js → index-BQC95Boo.js} +4 -4
  7. package/client/dist/index.html +1 -1
  8. package/client/lib/lib/assessment/coreTypes.d.ts +37 -0
  9. package/client/lib/lib/assessment/coreTypes.d.ts.map +1 -1
  10. package/client/lib/lib/assessment/resultTypes.d.ts +26 -1
  11. package/client/lib/lib/assessment/resultTypes.d.ts.map +1 -1
  12. package/client/lib/lib/securityPatterns/advancedExploitPatterns.d.ts +13 -0
  13. package/client/lib/lib/securityPatterns/advancedExploitPatterns.d.ts.map +1 -0
  14. package/client/lib/lib/securityPatterns/advancedExploitPatterns.js +504 -0
  15. package/client/lib/lib/securityPatterns/authSessionPatterns.d.ts +12 -0
  16. package/client/lib/lib/securityPatterns/authSessionPatterns.d.ts.map +1 -0
  17. package/client/lib/lib/securityPatterns/authSessionPatterns.js +357 -0
  18. package/client/lib/lib/securityPatterns/index.d.ts +18 -0
  19. package/client/lib/lib/securityPatterns/index.d.ts.map +1 -0
  20. package/client/lib/lib/securityPatterns/index.js +18 -0
  21. package/client/lib/lib/securityPatterns/injectionPatterns.d.ts +13 -0
  22. package/client/lib/lib/securityPatterns/injectionPatterns.d.ts.map +1 -0
  23. package/client/lib/lib/securityPatterns/injectionPatterns.js +356 -0
  24. package/client/lib/lib/securityPatterns/resourceExhaustionPatterns.d.ts +12 -0
  25. package/client/lib/lib/securityPatterns/resourceExhaustionPatterns.d.ts.map +1 -0
  26. package/client/lib/lib/securityPatterns/resourceExhaustionPatterns.js +215 -0
  27. package/client/lib/lib/securityPatterns/toolSpecificPatterns.d.ts +13 -0
  28. package/client/lib/lib/securityPatterns/toolSpecificPatterns.d.ts.map +1 -0
  29. package/client/lib/lib/securityPatterns/toolSpecificPatterns.js +373 -0
  30. package/client/lib/lib/securityPatterns/types.d.ts +20 -0
  31. package/client/lib/lib/securityPatterns/types.d.ts.map +1 -0
  32. package/client/lib/lib/securityPatterns/types.js +6 -0
  33. package/client/lib/lib/securityPatterns/utils.d.ts +56 -0
  34. package/client/lib/lib/securityPatterns/utils.d.ts.map +1 -0
  35. package/client/lib/lib/securityPatterns/utils.js +96 -0
  36. package/client/lib/lib/securityPatterns/validationPatterns.d.ts +13 -0
  37. package/client/lib/lib/securityPatterns/validationPatterns.d.ts.map +1 -0
  38. package/client/lib/lib/securityPatterns/validationPatterns.js +110 -0
  39. package/client/lib/lib/securityPatterns.d.ts +18 -69
  40. package/client/lib/lib/securityPatterns.d.ts.map +1 -1
  41. package/client/lib/lib/securityPatterns.js +18 -1946
  42. package/client/lib/services/assessment/AssessmentOrchestrator.d.ts +4 -1
  43. package/client/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
  44. package/client/lib/services/assessment/helpers/ExternalAPIDependencyDetector.d.ts +96 -5
  45. package/client/lib/services/assessment/helpers/ExternalAPIDependencyDetector.d.ts.map +1 -1
  46. package/client/lib/services/assessment/helpers/ExternalAPIDependencyDetector.js +202 -16
  47. package/client/lib/services/assessment/helpers/StdioTransportDetector.d.ts +137 -0
  48. package/client/lib/services/assessment/helpers/StdioTransportDetector.d.ts.map +1 -0
  49. package/client/lib/services/assessment/helpers/StdioTransportDetector.js +315 -0
  50. package/client/lib/services/assessment/helpers/ToolAnnotationExtractor.d.ts +34 -0
  51. package/client/lib/services/assessment/helpers/ToolAnnotationExtractor.d.ts.map +1 -0
  52. package/client/lib/services/assessment/helpers/ToolAnnotationExtractor.js +85 -0
  53. package/client/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts +17 -0
  54. package/client/lib/services/assessment/modules/ErrorHandlingAssessor.d.ts.map +1 -1
  55. package/client/lib/services/assessment/modules/ErrorHandlingAssessor.js +162 -10
  56. package/client/lib/services/assessment/modules/ProtocolComplianceAssessor.d.ts.map +1 -1
  57. package/client/lib/services/assessment/modules/ProtocolComplianceAssessor.js +30 -0
  58. package/client/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
  59. package/client/lib/services/assessment/modules/SecurityAssessor.js +6 -0
  60. package/client/lib/services/assessment/modules/securityTests/AnnotationAwareSeverity.d.ts +55 -0
  61. package/client/lib/services/assessment/modules/securityTests/AnnotationAwareSeverity.d.ts.map +1 -0
  62. package/client/lib/services/assessment/modules/securityTests/AnnotationAwareSeverity.js +135 -0
  63. package/client/lib/services/assessment/modules/securityTests/SafeResponseDetector.d.ts +6 -0
  64. package/client/lib/services/assessment/modules/securityTests/SafeResponseDetector.d.ts.map +1 -1
  65. package/client/lib/services/assessment/modules/securityTests/SafeResponseDetector.js +9 -1
  66. package/client/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts +20 -0
  67. package/client/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.d.ts.map +1 -1
  68. package/client/lib/services/assessment/modules/securityTests/SecurityPatternLibrary.js +37 -0
  69. package/client/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts +11 -1
  70. package/client/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts.map +1 -1
  71. package/client/lib/services/assessment/modules/securityTests/SecurityPayloadTester.js +26 -1
  72. package/client/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +1 -1
  73. package/client/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -1
  74. package/client/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +10 -1
  75. package/client/lib/services/assessment/modules/securityTests/index.d.ts +1 -0
  76. package/client/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -1
  77. package/client/lib/services/assessment/modules/securityTests/index.js +1 -0
  78. package/client/package.json +1 -1
  79. package/package.json +1 -1
  80. package/server/package.json +1 -1
@@ -0,0 +1,315 @@
1
+ /**
2
+ * Stdio Transport Detector
3
+ *
4
+ * Identifies stdio transport support from multiple sources:
5
+ * 1. server.json manifest (packages[0].transport.type)
6
+ * 2. package.json bin entries (indicates CLI/stdio)
7
+ * 3. Source code scanning for transport patterns
8
+ * 4. Runtime transport configuration
9
+ *
10
+ * This fixes Issue #172: C6/F6 incorrectly fails for valid stdio servers
11
+ * because transport detection previously relied solely on serverInfo metadata.
12
+ *
13
+ * @module helpers/StdioTransportDetector
14
+ */
15
+ /**
16
+ * Detects transport capabilities from multiple sources.
17
+ *
18
+ * Detection priority (highest confidence first):
19
+ * 1. Runtime transport configuration (actual runtime proof)
20
+ * 2. server.json transport declaration (explicit manifest)
21
+ * 3. package.json bin entries (strong CLI/stdio indicator)
22
+ * 4. Source code patterns (StdioServerTransport, mcp.run, etc.)
23
+ *
24
+ * @public
25
+ */
26
+ export class StdioTransportDetector {
27
+ /**
28
+ * TypeScript/JavaScript patterns for stdio transport
29
+ */
30
+ STDIO_CODE_PATTERNS = [
31
+ {
32
+ pattern: /StdioServerTransport/,
33
+ description: "Uses StdioServerTransport class",
34
+ },
35
+ {
36
+ pattern: /from\s*['"]@modelcontextprotocol\/sdk\/server\/stdio/,
37
+ description: "Imports MCP SDK stdio module",
38
+ },
39
+ {
40
+ pattern: /from\s*['"].*\/stdio/,
41
+ description: "Imports stdio transport module",
42
+ },
43
+ {
44
+ pattern: /transport\s*[:=]\s*['"]stdio['"]/i,
45
+ description: "Declares transport as stdio",
46
+ },
47
+ {
48
+ pattern: /createStdioTransport/,
49
+ description: "Creates stdio transport",
50
+ },
51
+ ];
52
+ /**
53
+ * Python/FastMCP patterns for stdio transport
54
+ */
55
+ PYTHON_STDIO_PATTERNS = [
56
+ {
57
+ pattern: /mcp\.run\s*\(\s*transport\s*=\s*['"]stdio['"]/,
58
+ description: "FastMCP run with stdio transport",
59
+ },
60
+ {
61
+ pattern: /StdioTransport/,
62
+ description: "Uses StdioTransport class",
63
+ },
64
+ {
65
+ pattern: /transport\s*=\s*['"]stdio['"]/i,
66
+ description: "Python stdio transport declaration",
67
+ },
68
+ {
69
+ pattern: /from\s+mcp\.server\.stdio\s+import/,
70
+ description: "Imports MCP stdio module (Python)",
71
+ },
72
+ ];
73
+ /**
74
+ * HTTP/SSE transport patterns
75
+ */
76
+ HTTP_CODE_PATTERNS = [
77
+ {
78
+ pattern: /StreamableHTTPServerTransport/,
79
+ transport: "http",
80
+ description: "Uses StreamableHTTPServerTransport",
81
+ },
82
+ {
83
+ pattern: /SSEServerTransport/,
84
+ transport: "sse",
85
+ description: "Uses SSEServerTransport",
86
+ },
87
+ {
88
+ pattern: /transport\s*[:=]\s*['"]http['"]/i,
89
+ transport: "http",
90
+ description: "Declares transport as http",
91
+ },
92
+ {
93
+ pattern: /transport\s*[:=]\s*['"]sse['"]/i,
94
+ transport: "sse",
95
+ description: "Declares transport as sse",
96
+ },
97
+ {
98
+ pattern: /transport\s*[:=]\s*['"]streamable-http['"]/i,
99
+ transport: "http",
100
+ description: "Declares transport as streamable-http",
101
+ },
102
+ {
103
+ pattern: /express|fastify|koa|hono/i,
104
+ transport: "http",
105
+ description: "Uses HTTP framework",
106
+ },
107
+ {
108
+ pattern: /app\.listen\s*\(/,
109
+ transport: "http",
110
+ description: "HTTP server listen call",
111
+ },
112
+ ];
113
+ /**
114
+ * File patterns to skip during source code scanning
115
+ */
116
+ SKIP_FILE_PATTERNS = [
117
+ /node_modules/i,
118
+ /\.test\.(ts|js|tsx|jsx|py)$/i,
119
+ /\.spec\.(ts|js|tsx|jsx|py)$/i,
120
+ /\.d\.ts$/i,
121
+ /package-lock\.json$/i,
122
+ /yarn\.lock$/i,
123
+ /\.map$/i,
124
+ /\.git\//i,
125
+ /dist\//i,
126
+ /build\//i,
127
+ /__tests__\//i,
128
+ /__mocks__\//i,
129
+ /__pycache__\//i,
130
+ /\.pytest_cache\//i,
131
+ ];
132
+ /** Maximum file size for source scanning (500KB) */
133
+ MAX_FILE_SIZE = 500_000;
134
+ /**
135
+ * Detect transport capabilities from all available sources.
136
+ *
137
+ * @param sourceCodeFiles - Map of file paths to content
138
+ * @param packageJson - Parsed package.json content
139
+ * @param serverJson - Parsed server.json content
140
+ * @param runtimeTransport - Transport type from runtime config
141
+ * @returns Transport detection results
142
+ */
143
+ detect(sourceCodeFiles, packageJson, serverJson, runtimeTransport) {
144
+ const evidence = [];
145
+ const detectedTransports = new Set();
146
+ // 1. Runtime transport config (highest confidence)
147
+ if (runtimeTransport) {
148
+ detectedTransports.add(runtimeTransport);
149
+ evidence.push({
150
+ source: "runtime-config",
151
+ transport: runtimeTransport,
152
+ confidence: "high",
153
+ detail: `Runtime transport configured as ${runtimeTransport}`,
154
+ });
155
+ }
156
+ // 2. server.json transport declaration
157
+ if (serverJson?.packages?.[0]?.transport?.type) {
158
+ const transportType = serverJson.packages[0].transport
159
+ .type;
160
+ if (this.isValidTransport(transportType)) {
161
+ detectedTransports.add(transportType);
162
+ evidence.push({
163
+ source: "server.json",
164
+ transport: transportType,
165
+ confidence: "high",
166
+ detail: `server.json declares transport.type="${transportType}"`,
167
+ });
168
+ }
169
+ }
170
+ // 3. package.json bin entries (strong stdio indicator)
171
+ if (packageJson?.bin) {
172
+ const binEntry = typeof packageJson.bin === "string"
173
+ ? packageJson.bin
174
+ : Object.keys(packageJson.bin)[0];
175
+ if (binEntry) {
176
+ detectedTransports.add("stdio");
177
+ evidence.push({
178
+ source: "package.json",
179
+ transport: "stdio",
180
+ confidence: "high",
181
+ detail: `package.json has bin entry (CLI tools use stdio)`,
182
+ });
183
+ }
184
+ }
185
+ // 4. Source code scanning
186
+ const sourceCodeScanned = sourceCodeFiles !== undefined && sourceCodeFiles.size > 0;
187
+ if (sourceCodeFiles !== undefined && sourceCodeFiles.size > 0) {
188
+ const sourceEvidence = this.scanSourceCode(sourceCodeFiles);
189
+ for (const ev of sourceEvidence) {
190
+ evidence.push(ev);
191
+ detectedTransports.add(ev.transport);
192
+ }
193
+ }
194
+ // Compute overall confidence
195
+ const confidence = this.computeConfidence(evidence);
196
+ return {
197
+ detectedTransports,
198
+ confidence,
199
+ evidence,
200
+ supportsStdio: detectedTransports.has("stdio"),
201
+ supportsHTTP: detectedTransports.has("http"),
202
+ supportsSSE: detectedTransports.has("sse"),
203
+ sourceCodeScanned,
204
+ };
205
+ }
206
+ /**
207
+ * Scan source code files for transport patterns.
208
+ *
209
+ * @param sourceCodeFiles - Map of file paths to content
210
+ * @returns Array of evidence from source code analysis
211
+ */
212
+ scanSourceCode(sourceCodeFiles) {
213
+ const evidence = [];
214
+ const foundPatterns = new Set(); // Deduplicate
215
+ sourceCodeFiles.forEach((content, filePath) => {
216
+ // Skip test files, node_modules, etc.
217
+ if (this.shouldSkipFile(filePath))
218
+ return;
219
+ // Skip oversized files
220
+ if (content.length > this.MAX_FILE_SIZE)
221
+ return;
222
+ // Check stdio patterns (TypeScript/JavaScript)
223
+ for (const { pattern, description } of this.STDIO_CODE_PATTERNS) {
224
+ const key = `stdio:${description}`;
225
+ if (!foundPatterns.has(key) && pattern.test(content)) {
226
+ foundPatterns.add(key);
227
+ evidence.push({
228
+ source: "source-code",
229
+ transport: "stdio",
230
+ confidence: "medium",
231
+ detail: `${description} in ${this.shortenPath(filePath)}`,
232
+ });
233
+ }
234
+ }
235
+ // Check stdio patterns (Python)
236
+ for (const { pattern, description } of this.PYTHON_STDIO_PATTERNS) {
237
+ const key = `stdio-py:${description}`;
238
+ if (!foundPatterns.has(key) && pattern.test(content)) {
239
+ foundPatterns.add(key);
240
+ evidence.push({
241
+ source: "source-code",
242
+ transport: "stdio",
243
+ confidence: "medium",
244
+ detail: `${description} in ${this.shortenPath(filePath)}`,
245
+ });
246
+ }
247
+ }
248
+ // Check HTTP/SSE patterns
249
+ for (const { pattern, transport, description } of this
250
+ .HTTP_CODE_PATTERNS) {
251
+ const key = `${transport}:${description}`;
252
+ if (!foundPatterns.has(key) && pattern.test(content)) {
253
+ foundPatterns.add(key);
254
+ evidence.push({
255
+ source: "source-code",
256
+ transport,
257
+ confidence: "medium",
258
+ detail: `${description} in ${this.shortenPath(filePath)}`,
259
+ });
260
+ }
261
+ }
262
+ });
263
+ return evidence;
264
+ }
265
+ /**
266
+ * Check if a transport type is valid.
267
+ */
268
+ isValidTransport(transport) {
269
+ return ["stdio", "http", "sse"].includes(transport);
270
+ }
271
+ /**
272
+ * Check if a file should be skipped during scanning.
273
+ */
274
+ shouldSkipFile(filePath) {
275
+ return this.SKIP_FILE_PATTERNS.some((pattern) => pattern.test(filePath));
276
+ }
277
+ /**
278
+ * Shorten file path for display.
279
+ */
280
+ shortenPath(filePath) {
281
+ const parts = filePath.split("/");
282
+ if (parts.length > 2) {
283
+ return `.../${parts.slice(-2).join("/")}`;
284
+ }
285
+ return filePath;
286
+ }
287
+ /**
288
+ * Compute overall confidence from collected evidence.
289
+ *
290
+ * Confidence rules:
291
+ * - High: Any high-confidence evidence present
292
+ * - Medium: Only medium-confidence evidence OR multiple sources agree
293
+ * - Low: No evidence or only weak patterns
294
+ */
295
+ computeConfidence(evidence) {
296
+ if (evidence.length === 0) {
297
+ return "low";
298
+ }
299
+ // Any high-confidence evidence = overall high
300
+ if (evidence.some((e) => e.confidence === "high")) {
301
+ return "high";
302
+ }
303
+ // Multiple sources agreeing boosts confidence
304
+ const uniqueSources = new Set(evidence.map((e) => e.source));
305
+ if (uniqueSources.size >= 2) {
306
+ return "high";
307
+ }
308
+ // Multiple medium-confidence findings = overall medium
309
+ if (evidence.length >= 2) {
310
+ return "medium";
311
+ }
312
+ // Single medium-confidence finding
313
+ return "medium";
314
+ }
315
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Tool Annotation Extractor
3
+ *
4
+ * Pre-extracts annotations from all tools for security assessment context.
5
+ * Issue #170: Enables annotation-aware security severity adjustment.
6
+ *
7
+ * This helper is used during context preparation to extract annotations
8
+ * BEFORE security testing begins, allowing SecurityAssessor to adjust
9
+ * vulnerability severity based on tool capabilities.
10
+ *
11
+ * @module helpers/ToolAnnotationExtractor
12
+ */
13
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
14
+ import type { ToolAnnotationsContext } from "../../../lib/assessment/coreTypes.js";
15
+ /**
16
+ * Extract tool annotations context from all tools.
17
+ *
18
+ * Iterates through all tools, extracts annotations using the existing
19
+ * 5-tier priority system, and computes server-level flags for read-only
20
+ * and closed-world servers.
21
+ *
22
+ * @param tools - Array of MCP tools to extract annotations from
23
+ * @returns ToolAnnotationsContext with per-tool annotations and server flags
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const context = extractToolAnnotationsContext(tools);
28
+ * if (context.serverIsReadOnly) {
29
+ * console.log("Server is 100% read-only");
30
+ * }
31
+ * ```
32
+ */
33
+ export declare function extractToolAnnotationsContext(tools: Tool[]): ToolAnnotationsContext;
34
+ //# sourceMappingURL=ToolAnnotationExtractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToolAnnotationExtractor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/helpers/ToolAnnotationExtractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAE/D,OAAO,KAAK,EACV,sBAAsB,EAEvB,MAAM,4BAA4B,CAAC;AAEpC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,IAAI,EAAE,GACZ,sBAAsB,CAkExB"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Tool Annotation Extractor
3
+ *
4
+ * Pre-extracts annotations from all tools for security assessment context.
5
+ * Issue #170: Enables annotation-aware security severity adjustment.
6
+ *
7
+ * This helper is used during context preparation to extract annotations
8
+ * BEFORE security testing begins, allowing SecurityAssessor to adjust
9
+ * vulnerability severity based on tool capabilities.
10
+ *
11
+ * @module helpers/ToolAnnotationExtractor
12
+ */
13
+ import { extractAnnotations } from "../modules/annotations/AlignmentChecker.js";
14
+ /**
15
+ * Extract tool annotations context from all tools.
16
+ *
17
+ * Iterates through all tools, extracts annotations using the existing
18
+ * 5-tier priority system, and computes server-level flags for read-only
19
+ * and closed-world servers.
20
+ *
21
+ * @param tools - Array of MCP tools to extract annotations from
22
+ * @returns ToolAnnotationsContext with per-tool annotations and server flags
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const context = extractToolAnnotationsContext(tools);
27
+ * if (context.serverIsReadOnly) {
28
+ * console.log("Server is 100% read-only");
29
+ * }
30
+ * ```
31
+ */
32
+ export function extractToolAnnotationsContext(tools) {
33
+ const toolAnnotations = new Map();
34
+ let readOnlyCount = 0;
35
+ let closedWorldCount = 0;
36
+ let annotatedCount = 0;
37
+ for (const tool of tools) {
38
+ // Use existing extraction logic with 5-tier priority
39
+ const extracted = extractAnnotations(tool);
40
+ // Validate extracted data has valid source
41
+ if (!extracted || !extracted.source) {
42
+ continue; // Skip tools with invalid extraction
43
+ }
44
+ // Convert to SecurityAnnotations (subset of ExtractedAnnotations)
45
+ // Ensure boolean fields are properly validated
46
+ const securityAnnotations = {
47
+ readOnlyHint: typeof extracted.readOnlyHint === "boolean"
48
+ ? extracted.readOnlyHint
49
+ : undefined,
50
+ destructiveHint: typeof extracted.destructiveHint === "boolean"
51
+ ? extracted.destructiveHint
52
+ : undefined,
53
+ idempotentHint: typeof extracted.idempotentHint === "boolean"
54
+ ? extracted.idempotentHint
55
+ : undefined,
56
+ openWorldHint: typeof extracted.openWorldHint === "boolean"
57
+ ? extracted.openWorldHint
58
+ : undefined,
59
+ source: extracted.source,
60
+ };
61
+ toolAnnotations.set(tool.name, securityAnnotations);
62
+ // Count tools with annotations
63
+ if (extracted.source !== "none") {
64
+ annotatedCount++;
65
+ // Count read-only tools
66
+ if (extracted.readOnlyHint === true) {
67
+ readOnlyCount++;
68
+ }
69
+ // Count closed-world tools
70
+ if (extracted.openWorldHint === false) {
71
+ closedWorldCount++;
72
+ }
73
+ }
74
+ }
75
+ const totalCount = tools.length;
76
+ return {
77
+ toolAnnotations,
78
+ // Server is read-only only if ALL annotated tools are read-only
79
+ serverIsReadOnly: annotatedCount > 0 && readOnlyCount === annotatedCount,
80
+ // Server is closed only if ALL annotated tools are closed
81
+ serverIsClosed: annotatedCount > 0 && closedWorldCount === annotatedCount,
82
+ annotatedToolCount: annotatedCount,
83
+ totalToolCount: totalCount,
84
+ };
85
+ }
@@ -20,16 +20,22 @@ export declare class ErrorHandlingAssessor extends BaseAssessor {
20
20
  private testExcessiveInput;
21
21
  private getToolSchema;
22
22
  private generateWrongTypeParams;
23
+ /**
24
+ * Issue #173: Return type for generateInvalidValueParams with metadata
25
+ * Tracks which parameter is being tested and whether it's required
26
+ */
23
27
  private generateInvalidValueParams;
24
28
  private generateParamsWithValue;
25
29
  /**
26
30
  * Analyze invalid_values response to determine scoring impact
27
31
  * Issue #99: Contextual empty string validation scoring
32
+ * Issue #173: Bonus points for suggestions and graceful degradation
28
33
  *
29
34
  * Classifications:
30
35
  * - safe_rejection: Tool rejected with error (no penalty)
31
36
  * - safe_reflection: Tool stored/echoed without executing (no penalty)
32
37
  * - defensive_programming: Tool handled gracefully (no penalty)
38
+ * - graceful_degradation: Optional param handled with neutral response (no penalty + bonus)
33
39
  * - execution_detected: Tool executed input (penalty)
34
40
  * - unknown: Cannot determine (partial penalty)
35
41
  */
@@ -43,6 +49,17 @@ export declare class ErrorHandlingAssessor extends BaseAssessor {
43
49
  * Examples: "Deleted 0 keys", "No results found", "Query returned 0"
44
50
  */
45
51
  private isDefensiveProgrammingResponse;
52
+ /**
53
+ * Issue #173: Detect helpful suggestion patterns in error responses
54
+ * Patterns like: "Did you mean: Button, Checkbox?"
55
+ * Returns extracted suggestions for bonus scoring
56
+ */
57
+ private detectSuggestionPatterns;
58
+ /**
59
+ * Issue #173: Check for neutral/graceful responses on optional parameters
60
+ * These indicate the tool handled empty/missing optional input appropriately
61
+ */
62
+ private isNeutralGracefulResponse;
46
63
  private calculateMetrics;
47
64
  private determineErrorHandlingStatus;
48
65
  private generateExplanation;
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorHandlingAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ErrorHandlingAssessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,uBAAuB,EAKxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAU9D,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,eAAe,CAAkB;gBAE7B,MAAM,EAAE,uBAAuB;IAOrC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA6G1E,OAAO,CAAC,qBAAqB;YAuDf,qBAAqB;YAiCrB,qBAAqB;YA+IrB,cAAc;YA8Hd,iBAAiB;YAyGjB,kBAAkB;IAwGhC,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,uBAAuB;IAkC/B,OAAO,CAAC,0BAA0B;IAkClC,OAAO,CAAC,uBAAuB;IA4B/B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,4BAA4B;IAgEpC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAc/B;;;OAGG;IACH,OAAO,CAAC,8BAA8B;IAetC,OAAO,CAAC,gBAAgB;IA8GxB,OAAO,CAAC,4BAA4B;IAapC,OAAO,CAAC,mBAAmB;IAuE3B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAgB9B,OAAO,CAAC,uBAAuB;CA4ChC"}
1
+ {"version":3,"file":"ErrorHandlingAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ErrorHandlingAssessor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,uBAAuB,EAKxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAU9D,qBAAa,qBAAsB,SAAQ,YAAY;IACrD,OAAO,CAAC,iBAAiB,CAA4B;IACrD,OAAO,CAAC,oBAAoB,CAAuB;IACnD,OAAO,CAAC,eAAe,CAAkB;gBAE7B,MAAM,EAAE,uBAAuB;IAOrC,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA6G1E,OAAO,CAAC,qBAAqB;YAuDf,qBAAqB;YAiCrB,qBAAqB;YA+IrB,cAAc;YA8Hd,iBAAiB;YAyIjB,kBAAkB;IAwGhC,OAAO,CAAC,aAAa;IAOrB,OAAO,CAAC,uBAAuB;IAkC/B;;;OAGG;IACH,OAAO,CAAC,0BAA0B;IAkDlC,OAAO,CAAC,uBAAuB;IA4B/B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,4BAA4B;IAyFpC;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAc/B;;;OAGG;IACH,OAAO,CAAC,8BAA8B;IAetC;;;;OAIG;IACH,OAAO,CAAC,wBAAwB;IAuChC;;;OAGG;IACH,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,gBAAgB;IAiJxB,OAAO,CAAC,4BAA4B;IAapC,OAAO,CAAC,mBAAmB;IAuE3B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAgB9B,OAAO,CAAC,uBAAuB;CA4ChC"}