@bryan-thompson/inspector-assessment-client 1.30.1 → 1.32.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 (69) hide show
  1. package/dist/assets/{OAuthCallback-BbE88qbF.js → OAuthCallback-Cl2ANLYP.js} +1 -1
  2. package/dist/assets/{OAuthDebugCallback-CfRYq1JG.js → OAuthDebugCallback-Ws62T4Ns.js} +1 -1
  3. package/dist/assets/{index-cHhcEXbr.css → index-BoUA5OL1.css} +3 -0
  4. package/dist/assets/{index-CsUB73MT.js → index-DaPIdOcS.js} +3746 -115
  5. package/dist/index.html +2 -2
  6. package/lib/lib/assessment/configTypes.d.ts +6 -0
  7. package/lib/lib/assessment/configTypes.d.ts.map +1 -1
  8. package/lib/lib/assessment/extendedTypes.d.ts +95 -0
  9. package/lib/lib/assessment/extendedTypes.d.ts.map +1 -1
  10. package/lib/lib/assessment/resultTypes.d.ts +14 -2
  11. package/lib/lib/assessment/resultTypes.d.ts.map +1 -1
  12. package/lib/lib/assessment/sharedSchemas.d.ts +140 -0
  13. package/lib/lib/assessment/sharedSchemas.d.ts.map +1 -0
  14. package/lib/lib/assessment/sharedSchemas.js +113 -0
  15. package/lib/lib/moduleScoring.d.ts.map +1 -1
  16. package/lib/lib/moduleScoring.js +5 -0
  17. package/lib/lib/securityPatterns.d.ts.map +1 -1
  18. package/lib/lib/securityPatterns.js +2 -2
  19. package/lib/services/assessment/AssessmentOrchestrator.d.ts +20 -18
  20. package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
  21. package/lib/services/assessment/AssessmentOrchestrator.js +143 -144
  22. package/lib/services/assessment/ResponseValidator.d.ts +10 -0
  23. package/lib/services/assessment/ResponseValidator.d.ts.map +1 -1
  24. package/lib/services/assessment/ResponseValidator.js +30 -6
  25. package/lib/services/assessment/config/performanceConfig.d.ts +2 -0
  26. package/lib/services/assessment/config/performanceConfig.d.ts.map +1 -1
  27. package/lib/services/assessment/config/performanceConfig.js +5 -33
  28. package/lib/services/assessment/config/performanceConfigSchemas.d.ts +111 -0
  29. package/lib/services/assessment/config/performanceConfigSchemas.d.ts.map +1 -0
  30. package/lib/services/assessment/config/performanceConfigSchemas.js +123 -0
  31. package/lib/services/assessment/modules/ConformanceAssessor.d.ts +64 -0
  32. package/lib/services/assessment/modules/ConformanceAssessor.d.ts.map +1 -0
  33. package/lib/services/assessment/modules/ConformanceAssessor.js +329 -0
  34. package/lib/services/assessment/modules/ResourceAssessor.d.ts +14 -0
  35. package/lib/services/assessment/modules/ResourceAssessor.d.ts.map +1 -1
  36. package/lib/services/assessment/modules/ResourceAssessor.js +226 -0
  37. package/lib/services/assessment/modules/TemporalAssessor.d.ts +14 -0
  38. package/lib/services/assessment/modules/TemporalAssessor.d.ts.map +1 -1
  39. package/lib/services/assessment/modules/TemporalAssessor.js +29 -1
  40. package/lib/services/assessment/modules/annotations/AlignmentChecker.d.ts +9 -0
  41. package/lib/services/assessment/modules/annotations/AlignmentChecker.d.ts.map +1 -1
  42. package/lib/services/assessment/modules/annotations/AlignmentChecker.js +97 -5
  43. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts +6 -4
  44. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts.map +1 -1
  45. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.js +58 -0
  46. package/lib/services/assessment/modules/annotations/index.d.ts +1 -1
  47. package/lib/services/assessment/modules/annotations/index.d.ts.map +1 -1
  48. package/lib/services/assessment/modules/annotations/index.js +2 -1
  49. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -1
  50. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +3 -3
  51. package/lib/services/assessment/registry/AssessorDefinitions.d.ts +38 -0
  52. package/lib/services/assessment/registry/AssessorDefinitions.d.ts.map +1 -0
  53. package/lib/services/assessment/registry/AssessorDefinitions.js +370 -0
  54. package/lib/services/assessment/registry/AssessorRegistry.d.ts +124 -0
  55. package/lib/services/assessment/registry/AssessorRegistry.d.ts.map +1 -0
  56. package/lib/services/assessment/registry/AssessorRegistry.js +321 -0
  57. package/lib/services/assessment/registry/estimators.d.ts +93 -0
  58. package/lib/services/assessment/registry/estimators.d.ts.map +1 -0
  59. package/lib/services/assessment/registry/estimators.js +176 -0
  60. package/lib/services/assessment/registry/index.d.ts +13 -0
  61. package/lib/services/assessment/registry/index.d.ts.map +1 -0
  62. package/lib/services/assessment/registry/index.js +16 -0
  63. package/lib/services/assessment/registry/types.d.ts +180 -0
  64. package/lib/services/assessment/registry/types.d.ts.map +1 -0
  65. package/lib/services/assessment/registry/types.js +35 -0
  66. package/lib/services/assessment/responseValidatorSchemas.d.ts +751 -0
  67. package/lib/services/assessment/responseValidatorSchemas.d.ts.map +1 -0
  68. package/lib/services/assessment/responseValidatorSchemas.js +244 -0
  69. package/package.json +1 -1
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Zod Schemas for Performance Configuration
3
+ *
4
+ * Runtime validation schemas for performance configuration.
5
+ * Replaces manual validatePerformanceConfig() function with declarative schemas.
6
+ *
7
+ * @module assessment/config/performanceConfigSchemas
8
+ * @see performanceConfig.ts for the interface definitions
9
+ * @see sharedSchemas.ts for PERF_CONFIG_RANGES constants
10
+ */
11
+ import { z } from "zod";
12
+ import { PERF_CONFIG_RANGES } from "../../../lib/assessment/sharedSchemas.js";
13
+ export { PERF_CONFIG_RANGES };
14
+ /**
15
+ * Schema for performance configuration fields.
16
+ * All fields are optional since partial configs are merged with defaults.
17
+ *
18
+ * Validation ranges are defined in PERF_CONFIG_RANGES (sharedSchemas.ts).
19
+ */
20
+ export declare const PerformanceConfigSchema: z.ZodObject<{
21
+ /**
22
+ * Interval in milliseconds between progress batch flushes.
23
+ */
24
+ batchFlushIntervalMs: z.ZodOptional<z.ZodNumber>;
25
+ /**
26
+ * Batch size for functionality assessment progress events.
27
+ */
28
+ functionalityBatchSize: z.ZodOptional<z.ZodNumber>;
29
+ /**
30
+ * Batch size for security assessment progress events.
31
+ */
32
+ securityBatchSize: z.ZodOptional<z.ZodNumber>;
33
+ /**
34
+ * Timeout for individual test scenario execution in milliseconds.
35
+ */
36
+ testTimeoutMs: z.ZodOptional<z.ZodNumber>;
37
+ /**
38
+ * Timeout for individual security payload tests in milliseconds.
39
+ */
40
+ securityTestTimeoutMs: z.ZodOptional<z.ZodNumber>;
41
+ /**
42
+ * Warning threshold for queue depth monitoring.
43
+ */
44
+ queueWarningThreshold: z.ZodOptional<z.ZodNumber>;
45
+ /**
46
+ * Maximum EventEmitter listeners to prevent Node.js warnings.
47
+ */
48
+ eventEmitterMaxListeners: z.ZodOptional<z.ZodNumber>;
49
+ }, "strip", z.ZodTypeAny, {
50
+ batchFlushIntervalMs?: number;
51
+ functionalityBatchSize?: number;
52
+ securityBatchSize?: number;
53
+ testTimeoutMs?: number;
54
+ securityTestTimeoutMs?: number;
55
+ queueWarningThreshold?: number;
56
+ eventEmitterMaxListeners?: number;
57
+ }, {
58
+ batchFlushIntervalMs?: number;
59
+ functionalityBatchSize?: number;
60
+ securityBatchSize?: number;
61
+ testTimeoutMs?: number;
62
+ securityTestTimeoutMs?: number;
63
+ queueWarningThreshold?: number;
64
+ eventEmitterMaxListeners?: number;
65
+ }>;
66
+ /**
67
+ * Type inferred from the schema.
68
+ * Equivalent to Partial<PerformanceConfig> from performanceConfig.ts
69
+ */
70
+ export type PartialPerformanceConfig = z.infer<typeof PerformanceConfigSchema>;
71
+ /**
72
+ * Validate a partial performance config using Zod.
73
+ * Drop-in replacement for the manual validatePerformanceConfig() function.
74
+ *
75
+ * @param config - Partial config to validate
76
+ * @returns Array of validation error messages (empty if valid)
77
+ */
78
+ export declare function validatePerformanceConfigWithZod(config: unknown): string[];
79
+ /**
80
+ * Parse and validate a performance config, returning the validated data.
81
+ * Throws ZodError if validation fails.
82
+ *
83
+ * @param config - Config to parse and validate
84
+ * @returns Validated partial config
85
+ * @throws ZodError if validation fails
86
+ */
87
+ export declare function parsePerformanceConfig(config: unknown): PartialPerformanceConfig;
88
+ /**
89
+ * Safely parse a performance config without throwing.
90
+ *
91
+ * @param config - Config to parse and validate
92
+ * @returns SafeParseResult with success status and data/error
93
+ */
94
+ export declare function safeParsePerformanceConfig(config: unknown): z.SafeParseReturnType<{
95
+ batchFlushIntervalMs?: number;
96
+ functionalityBatchSize?: number;
97
+ securityBatchSize?: number;
98
+ testTimeoutMs?: number;
99
+ securityTestTimeoutMs?: number;
100
+ queueWarningThreshold?: number;
101
+ eventEmitterMaxListeners?: number;
102
+ }, {
103
+ batchFlushIntervalMs?: number;
104
+ functionalityBatchSize?: number;
105
+ securityBatchSize?: number;
106
+ testTimeoutMs?: number;
107
+ securityTestTimeoutMs?: number;
108
+ queueWarningThreshold?: number;
109
+ eventEmitterMaxListeners?: number;
110
+ }>;
111
+ //# sourceMappingURL=performanceConfigSchemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performanceConfigSchemas.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/config/performanceConfigSchemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAG3E,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;IAClC;;OAEG;;IAcH;;OAEG;;IAcH;;OAEG;;IAcH;;OAEG;;IAcH;;OAEG;;IAcH;;OAEG;;IAcH;;OAEG;;;;;;;;;;;;;;;;;;EAaH,CAAC;AAEH;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE/E;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,EAAE,CAW1E;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,OAAO,GACd,wBAAwB,CAE1B;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,OAAO;;;;;;;;;;;;;;;;GAEzD"}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Zod Schemas for Performance Configuration
3
+ *
4
+ * Runtime validation schemas for performance configuration.
5
+ * Replaces manual validatePerformanceConfig() function with declarative schemas.
6
+ *
7
+ * @module assessment/config/performanceConfigSchemas
8
+ * @see performanceConfig.ts for the interface definitions
9
+ * @see sharedSchemas.ts for PERF_CONFIG_RANGES constants
10
+ */
11
+ import { z } from "zod";
12
+ // Import validation range constants from single source of truth
13
+ import { PERF_CONFIG_RANGES } from "../../../lib/assessment/sharedSchemas.js";
14
+ // Re-export for consumers who need the range constants
15
+ export { PERF_CONFIG_RANGES };
16
+ /**
17
+ * Schema for performance configuration fields.
18
+ * All fields are optional since partial configs are merged with defaults.
19
+ *
20
+ * Validation ranges are defined in PERF_CONFIG_RANGES (sharedSchemas.ts).
21
+ */
22
+ export const PerformanceConfigSchema = z.object({
23
+ /**
24
+ * Interval in milliseconds between progress batch flushes.
25
+ */
26
+ batchFlushIntervalMs: z
27
+ .number()
28
+ .int("batchFlushIntervalMs must be an integer")
29
+ .min(PERF_CONFIG_RANGES.batchFlushIntervalMs.min, `batchFlushIntervalMs must be >= ${PERF_CONFIG_RANGES.batchFlushIntervalMs.min}`)
30
+ .max(PERF_CONFIG_RANGES.batchFlushIntervalMs.max, `batchFlushIntervalMs must be <= ${PERF_CONFIG_RANGES.batchFlushIntervalMs.max}`)
31
+ .optional(),
32
+ /**
33
+ * Batch size for functionality assessment progress events.
34
+ */
35
+ functionalityBatchSize: z
36
+ .number()
37
+ .int("functionalityBatchSize must be an integer")
38
+ .min(PERF_CONFIG_RANGES.functionalityBatchSize.min, `functionalityBatchSize must be >= ${PERF_CONFIG_RANGES.functionalityBatchSize.min}`)
39
+ .max(PERF_CONFIG_RANGES.functionalityBatchSize.max, `functionalityBatchSize must be <= ${PERF_CONFIG_RANGES.functionalityBatchSize.max}`)
40
+ .optional(),
41
+ /**
42
+ * Batch size for security assessment progress events.
43
+ */
44
+ securityBatchSize: z
45
+ .number()
46
+ .int("securityBatchSize must be an integer")
47
+ .min(PERF_CONFIG_RANGES.securityBatchSize.min, `securityBatchSize must be >= ${PERF_CONFIG_RANGES.securityBatchSize.min}`)
48
+ .max(PERF_CONFIG_RANGES.securityBatchSize.max, `securityBatchSize must be <= ${PERF_CONFIG_RANGES.securityBatchSize.max}`)
49
+ .optional(),
50
+ /**
51
+ * Timeout for individual test scenario execution in milliseconds.
52
+ */
53
+ testTimeoutMs: z
54
+ .number()
55
+ .int("testTimeoutMs must be an integer")
56
+ .min(PERF_CONFIG_RANGES.testTimeoutMs.min, `testTimeoutMs must be >= ${PERF_CONFIG_RANGES.testTimeoutMs.min}`)
57
+ .max(PERF_CONFIG_RANGES.testTimeoutMs.max, `testTimeoutMs must be <= ${PERF_CONFIG_RANGES.testTimeoutMs.max}`)
58
+ .optional(),
59
+ /**
60
+ * Timeout for individual security payload tests in milliseconds.
61
+ */
62
+ securityTestTimeoutMs: z
63
+ .number()
64
+ .int("securityTestTimeoutMs must be an integer")
65
+ .min(PERF_CONFIG_RANGES.securityTestTimeoutMs.min, `securityTestTimeoutMs must be >= ${PERF_CONFIG_RANGES.securityTestTimeoutMs.min}`)
66
+ .max(PERF_CONFIG_RANGES.securityTestTimeoutMs.max, `securityTestTimeoutMs must be <= ${PERF_CONFIG_RANGES.securityTestTimeoutMs.max}`)
67
+ .optional(),
68
+ /**
69
+ * Warning threshold for queue depth monitoring.
70
+ */
71
+ queueWarningThreshold: z
72
+ .number()
73
+ .int("queueWarningThreshold must be an integer")
74
+ .min(PERF_CONFIG_RANGES.queueWarningThreshold.min, `queueWarningThreshold must be >= ${PERF_CONFIG_RANGES.queueWarningThreshold.min}`)
75
+ .max(PERF_CONFIG_RANGES.queueWarningThreshold.max, `queueWarningThreshold must be <= ${PERF_CONFIG_RANGES.queueWarningThreshold.max}`)
76
+ .optional(),
77
+ /**
78
+ * Maximum EventEmitter listeners to prevent Node.js warnings.
79
+ */
80
+ eventEmitterMaxListeners: z
81
+ .number()
82
+ .int("eventEmitterMaxListeners must be an integer")
83
+ .min(PERF_CONFIG_RANGES.eventEmitterMaxListeners.min, `eventEmitterMaxListeners must be >= ${PERF_CONFIG_RANGES.eventEmitterMaxListeners.min}`)
84
+ .max(PERF_CONFIG_RANGES.eventEmitterMaxListeners.max, `eventEmitterMaxListeners must be <= ${PERF_CONFIG_RANGES.eventEmitterMaxListeners.max}`)
85
+ .optional(),
86
+ });
87
+ /**
88
+ * Validate a partial performance config using Zod.
89
+ * Drop-in replacement for the manual validatePerformanceConfig() function.
90
+ *
91
+ * @param config - Partial config to validate
92
+ * @returns Array of validation error messages (empty if valid)
93
+ */
94
+ export function validatePerformanceConfigWithZod(config) {
95
+ const result = PerformanceConfigSchema.safeParse(config);
96
+ if (result.success) {
97
+ return [];
98
+ }
99
+ return result.error.errors.map((e) => {
100
+ const path = e.path.length > 0 ? `${e.path.join(".")}: ` : "";
101
+ return `${path}${e.message}`;
102
+ });
103
+ }
104
+ /**
105
+ * Parse and validate a performance config, returning the validated data.
106
+ * Throws ZodError if validation fails.
107
+ *
108
+ * @param config - Config to parse and validate
109
+ * @returns Validated partial config
110
+ * @throws ZodError if validation fails
111
+ */
112
+ export function parsePerformanceConfig(config) {
113
+ return PerformanceConfigSchema.parse(config);
114
+ }
115
+ /**
116
+ * Safely parse a performance config without throwing.
117
+ *
118
+ * @param config - Config to parse and validate
119
+ * @returns SafeParseResult with success status and data/error
120
+ */
121
+ export function safeParsePerformanceConfig(config) {
122
+ return PerformanceConfigSchema.safeParse(config);
123
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Conformance Assessor Module
3
+ *
4
+ * Integrates official MCP conformance tests from @modelcontextprotocol/conformance.
5
+ * Runs server-side conformance validation against the MCP specification.
6
+ *
7
+ * Requirements:
8
+ * - HTTP/SSE transport (requires serverUrl in config)
9
+ * - Opt-in via --conformance flag or assessmentCategories.conformance = true
10
+ *
11
+ * @module assessment/modules/ConformanceAssessor
12
+ */
13
+ import { BaseAssessor } from "./BaseAssessor.js";
14
+ import { AssessmentContext } from "../AssessmentOrchestrator.js";
15
+ import type { ConformanceAssessment } from "../../../lib/assessment/extendedTypes.js";
16
+ /**
17
+ * Conformance Assessor
18
+ *
19
+ * Runs official MCP conformance tests against the server.
20
+ * Requires HTTP/SSE transport with serverUrl available.
21
+ */
22
+ export declare class ConformanceAssessor extends BaseAssessor<ConformanceAssessment> {
23
+ /**
24
+ * Run conformance assessment
25
+ */
26
+ assess(context: AssessmentContext): Promise<ConformanceAssessment>;
27
+ /**
28
+ * Run a single conformance scenario
29
+ */
30
+ private runScenario;
31
+ /**
32
+ * Find the checks.json file in the results directory
33
+ */
34
+ private findChecksFile;
35
+ /**
36
+ * Parse checks.json file from conformance results
37
+ */
38
+ private parseChecksFile;
39
+ /**
40
+ * Check if the MCP conformance package is available
41
+ */
42
+ private isConformancePackageAvailable;
43
+ /**
44
+ * Cleanup temporary directory
45
+ */
46
+ private cleanupTempDir;
47
+ /**
48
+ * Determine overall conformance status
49
+ */
50
+ private determineConformanceStatus;
51
+ /**
52
+ * Generate human-readable explanation
53
+ */
54
+ private generateExplanation;
55
+ /**
56
+ * Generate recommendations based on failures
57
+ */
58
+ private generateRecommendations;
59
+ /**
60
+ * Create a skipped result when conformance tests cannot run
61
+ */
62
+ private createSkippedResult;
63
+ }
64
+ //# sourceMappingURL=ConformanceAssessor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConformanceAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ConformanceAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EACV,qBAAqB,EAGtB,MAAM,gCAAgC,CAAC;AAgCxC;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,YAAY,CAAC,qBAAqB,CAAC;IAC1E;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAkGxE;;OAEG;YACW,WAAW;IAwEzB;;OAEG;IACH,OAAO,CAAC,cAAc;IAwBtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAmBvB;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAarC;;OAEG;IACH,OAAO,CAAC,cAAc;IAQtB;;OAEG;IACH,OAAO,CAAC,0BAA0B;IA+BlC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAyB3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA+C/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAmB5B"}
@@ -0,0 +1,329 @@
1
+ /**
2
+ * Conformance Assessor Module
3
+ *
4
+ * Integrates official MCP conformance tests from @modelcontextprotocol/conformance.
5
+ * Runs server-side conformance validation against the MCP specification.
6
+ *
7
+ * Requirements:
8
+ * - HTTP/SSE transport (requires serverUrl in config)
9
+ * - Opt-in via --conformance flag or assessmentCategories.conformance = true
10
+ *
11
+ * @module assessment/modules/ConformanceAssessor
12
+ */
13
+ import { execFileSync } from "child_process";
14
+ import * as fs from "fs";
15
+ import * as path from "path";
16
+ import * as os from "os";
17
+ import { BaseAssessor } from "./BaseAssessor.js";
18
+ /**
19
+ * Version of the conformance package we're integrating with
20
+ */
21
+ const CONFORMANCE_PACKAGE_VERSION = "0.1.9";
22
+ /**
23
+ * Available server scenarios from the conformance package
24
+ * Updated for @modelcontextprotocol/conformance v0.1.9+
25
+ */
26
+ const SERVER_SCENARIOS = [
27
+ "server-initialize",
28
+ "tools-list",
29
+ "tools-call-simple-text",
30
+ "resources-list",
31
+ "resources-read-text",
32
+ "prompts-list",
33
+ "prompts-get-simple",
34
+ ];
35
+ /**
36
+ * Conformance Assessor
37
+ *
38
+ * Runs official MCP conformance tests against the server.
39
+ * Requires HTTP/SSE transport with serverUrl available.
40
+ */
41
+ export class ConformanceAssessor extends BaseAssessor {
42
+ /**
43
+ * Run conformance assessment
44
+ */
45
+ async assess(context) {
46
+ const serverUrl = context.config.serverUrl;
47
+ // Check if serverUrl is available (required for conformance tests)
48
+ if (!serverUrl) {
49
+ this.logger.info("Conformance tests skipped: serverUrl not available (requires HTTP/SSE transport)");
50
+ return this.createSkippedResult("Server URL not available. Conformance tests require HTTP or SSE transport.");
51
+ }
52
+ // Check if conformance package is available
53
+ if (!this.isConformancePackageAvailable()) {
54
+ this.logger.warn("MCP conformance package not available. Install with: npm install -g @modelcontextprotocol/conformance");
55
+ return this.createSkippedResult("MCP conformance package not installed. Run: npm install -g @modelcontextprotocol/conformance");
56
+ }
57
+ this.logger.info(`Running conformance tests against: ${serverUrl}`);
58
+ const scenarios = [];
59
+ const allChecks = [];
60
+ let passedScenarios = 0;
61
+ let totalScenarios = 0;
62
+ // Run each server scenario
63
+ for (const scenario of SERVER_SCENARIOS) {
64
+ totalScenarios++;
65
+ try {
66
+ const scenarioResult = await this.runScenario(serverUrl, scenario);
67
+ scenarios.push(scenarioResult);
68
+ // Count scenario pass/fail (not individual checks)
69
+ if (scenarioResult.status === "pass") {
70
+ passedScenarios++;
71
+ }
72
+ // Aggregate any detailed checks for reporting
73
+ for (const check of scenarioResult.checks) {
74
+ allChecks.push(check);
75
+ }
76
+ this.testCount++;
77
+ }
78
+ catch (error) {
79
+ // Log error but continue with other scenarios
80
+ this.logger.warn(`Scenario ${scenario} failed: ${error instanceof Error ? error.message : String(error)}`);
81
+ scenarios.push({
82
+ name: scenario,
83
+ status: "skip",
84
+ checks: [],
85
+ });
86
+ }
87
+ }
88
+ // Calculate compliance score based on scenarios
89
+ const complianceScore = totalScenarios > 0
90
+ ? Math.round((passedScenarios / totalScenarios) * 100)
91
+ : 0;
92
+ // Determine overall status
93
+ const status = this.determineConformanceStatus(passedScenarios, totalScenarios, scenarios);
94
+ // Generate explanation and recommendations
95
+ const explanation = this.generateExplanation(status, passedScenarios, totalScenarios, scenarios);
96
+ const recommendations = this.generateRecommendations(scenarios, allChecks);
97
+ return {
98
+ status,
99
+ conformanceVersion: CONFORMANCE_PACKAGE_VERSION,
100
+ protocolVersion: context.config.mcpProtocolVersion || "2025-06",
101
+ scenarios,
102
+ officialChecks: allChecks,
103
+ passedChecks: passedScenarios,
104
+ totalChecks: totalScenarios,
105
+ complianceScore,
106
+ explanation,
107
+ recommendations,
108
+ };
109
+ }
110
+ /**
111
+ * Run a single conformance scenario
112
+ */
113
+ async runScenario(serverUrl, scenario) {
114
+ const startTime = Date.now();
115
+ try {
116
+ // Create temp directory for results
117
+ const resultsDir = fs.mkdtempSync(path.join(os.tmpdir(), "mcp-conformance-"));
118
+ // Run conformance CLI (results are written to checks.json, not stdout)
119
+ execFileSync("npx", [
120
+ "@modelcontextprotocol/conformance",
121
+ "server",
122
+ "--url",
123
+ serverUrl,
124
+ "--scenario",
125
+ scenario,
126
+ ], {
127
+ encoding: "utf-8",
128
+ timeout: 60000, // 60 second timeout per scenario
129
+ cwd: resultsDir,
130
+ stdio: ["pipe", "pipe", "pipe"],
131
+ });
132
+ // Parse results from checks.json
133
+ const checksPath = this.findChecksFile(resultsDir, scenario);
134
+ const checks = checksPath ? this.parseChecksFile(checksPath) : [];
135
+ // Determine scenario status
136
+ const hasFailures = checks.some((c) => c.status === "fail");
137
+ const status = hasFailures ? "fail" : "pass";
138
+ // Cleanup temp directory
139
+ this.cleanupTempDir(resultsDir);
140
+ return {
141
+ name: scenario,
142
+ status,
143
+ checks,
144
+ executionTime: Date.now() - startTime,
145
+ };
146
+ }
147
+ catch (error) {
148
+ this.logger.debug(`Scenario ${scenario} execution error: ${error instanceof Error ? error.message : String(error)}`);
149
+ // Return skip status for failed scenarios
150
+ return {
151
+ name: scenario,
152
+ status: "skip",
153
+ checks: [
154
+ {
155
+ name: `${scenario}-execution`,
156
+ status: "fail",
157
+ message: error instanceof Error
158
+ ? error.message
159
+ : "Scenario execution failed",
160
+ },
161
+ ],
162
+ executionTime: Date.now() - startTime,
163
+ };
164
+ }
165
+ }
166
+ /**
167
+ * Find the checks.json file in the results directory
168
+ */
169
+ findChecksFile(resultsDir, scenario) {
170
+ // Look for results in timestamped subdirectory
171
+ try {
172
+ const entries = fs.readdirSync(resultsDir);
173
+ for (const entry of entries) {
174
+ if (entry.startsWith(`server-${scenario}`) ||
175
+ entry.startsWith(scenario)) {
176
+ const checksPath = path.join(resultsDir, entry, "checks.json");
177
+ if (fs.existsSync(checksPath)) {
178
+ return checksPath;
179
+ }
180
+ }
181
+ }
182
+ }
183
+ catch {
184
+ // Directory might not exist
185
+ }
186
+ return undefined;
187
+ }
188
+ /**
189
+ * Parse checks.json file from conformance results
190
+ */
191
+ parseChecksFile(checksPath) {
192
+ try {
193
+ const content = fs.readFileSync(checksPath, "utf-8");
194
+ const results = JSON.parse(content);
195
+ return results.map((r) => ({
196
+ name: r.name,
197
+ status: r.status === "pass" ? "pass" : "fail",
198
+ message: r.message || "",
199
+ timestamp: r.timestamp,
200
+ }));
201
+ }
202
+ catch (error) {
203
+ this.logger.debug(`Failed to parse checks.json: ${error instanceof Error ? error.message : String(error)}`);
204
+ return [];
205
+ }
206
+ }
207
+ /**
208
+ * Check if the MCP conformance package is available
209
+ */
210
+ isConformancePackageAvailable() {
211
+ try {
212
+ execFileSync("npx", ["@modelcontextprotocol/conformance", "--version"], {
213
+ timeout: 30000,
214
+ stdio: "pipe",
215
+ encoding: "utf-8",
216
+ });
217
+ return true;
218
+ }
219
+ catch {
220
+ return false;
221
+ }
222
+ }
223
+ /**
224
+ * Cleanup temporary directory
225
+ */
226
+ cleanupTempDir(dirPath) {
227
+ try {
228
+ fs.rmSync(dirPath, { recursive: true, force: true });
229
+ }
230
+ catch {
231
+ // Ignore cleanup errors
232
+ }
233
+ }
234
+ /**
235
+ * Determine overall conformance status
236
+ */
237
+ determineConformanceStatus(passed, total, scenarios) {
238
+ // If no checks ran, need more info
239
+ if (total === 0) {
240
+ return "NEED_MORE_INFO";
241
+ }
242
+ // Check if any critical scenarios failed
243
+ const criticalScenarios = ["server-initialize", "tools-list"];
244
+ const criticalFailures = scenarios.filter((s) => criticalScenarios.includes(s.name) && s.status === "fail");
245
+ if (criticalFailures.length > 0) {
246
+ return "FAIL";
247
+ }
248
+ // Use pass rate for status
249
+ const passRate = passed / total;
250
+ if (passRate >= 0.9) {
251
+ return "PASS";
252
+ }
253
+ if (passRate >= 0.7) {
254
+ return "NEED_MORE_INFO";
255
+ }
256
+ return "FAIL";
257
+ }
258
+ /**
259
+ * Generate human-readable explanation
260
+ */
261
+ generateExplanation(status, passed, total, scenarios) {
262
+ const passRate = total > 0 ? Math.round((passed / total) * 100) : 0;
263
+ if (status === "PASS") {
264
+ return `Server passes ${passRate}% of official MCP conformance checks (${passed}/${total}). The implementation correctly follows the MCP protocol specification.`;
265
+ }
266
+ if (status === "NEED_MORE_INFO") {
267
+ const skipped = scenarios.filter((s) => s.status === "skip").length;
268
+ if (skipped > 0) {
269
+ return `Conformance testing partially completed. ${skipped} scenario(s) were skipped. ${passed}/${total} checks passed (${passRate}%).`;
270
+ }
271
+ return `Server passes ${passRate}% of conformance checks (${passed}/${total}). Some non-critical checks failed; review recommended.`;
272
+ }
273
+ // FAIL
274
+ const failures = scenarios.filter((s) => s.status === "fail");
275
+ return `Server fails conformance testing. ${failures.length} scenario(s) failed. Only ${passRate}% of checks passed (${passed}/${total}).`;
276
+ }
277
+ /**
278
+ * Generate recommendations based on failures
279
+ */
280
+ generateRecommendations(scenarios, checks) {
281
+ const recommendations = [];
282
+ // Check for initialization failures
283
+ const initScenario = scenarios.find((s) => s.name === "server-initialize");
284
+ if (initScenario?.status === "fail") {
285
+ recommendations.push("Fix initialization handshake issues - ensure server responds correctly to initialize request with valid serverInfo and capabilities.");
286
+ }
287
+ // Check for tools-list failures
288
+ const toolsListScenario = scenarios.find((s) => s.name === "tools-list");
289
+ if (toolsListScenario?.status === "fail") {
290
+ recommendations.push("Review tools/list implementation - ensure all tools have valid names, descriptions, and input schemas.");
291
+ }
292
+ // Check for skipped scenarios
293
+ const skipped = scenarios.filter((s) => s.status === "skip");
294
+ if (skipped.length > 0) {
295
+ recommendations.push(`Run conformance tests again to complete ${skipped.length} skipped scenario(s): ${skipped.map((s) => s.name).join(", ")}.`);
296
+ }
297
+ // Generic recommendations based on check failures
298
+ const failedChecks = checks.filter((c) => c.status === "fail");
299
+ if (failedChecks.length > 0 && recommendations.length < 3) {
300
+ recommendations.push("Review MCP specification at modelcontextprotocol.io for protocol compliance requirements.");
301
+ }
302
+ if (recommendations.length === 0) {
303
+ recommendations.push("Consider running full conformance suite periodically to catch regressions.");
304
+ }
305
+ return recommendations;
306
+ }
307
+ /**
308
+ * Create a skipped result when conformance tests cannot run
309
+ */
310
+ createSkippedResult(reason) {
311
+ return {
312
+ status: "NEED_MORE_INFO",
313
+ conformanceVersion: CONFORMANCE_PACKAGE_VERSION,
314
+ protocolVersion: this.config.mcpProtocolVersion || "2025-06",
315
+ scenarios: [],
316
+ officialChecks: [],
317
+ passedChecks: 0,
318
+ totalChecks: 0,
319
+ complianceScore: 0,
320
+ explanation: `Conformance testing skipped: ${reason}`,
321
+ recommendations: [
322
+ "Use HTTP or SSE transport to enable conformance testing.",
323
+ "Configure serverUrl in assessment configuration for STDIO servers.",
324
+ ],
325
+ skipped: true,
326
+ skipReason: reason,
327
+ };
328
+ }
329
+ }
@@ -28,6 +28,20 @@ export declare class ResourceAssessor extends BaseAssessor {
28
28
  */
29
29
  private inferDataClassification;
30
30
  private testResourceTemplate;
31
+ /**
32
+ * Issue #119, Challenge #14: Test URI injection vulnerabilities in resource templates
33
+ * Injects malicious payloads into URI parameters and checks for sensitive content leakage
34
+ */
35
+ private testParameterizedUriInjection;
36
+ /**
37
+ * Issue #119, Challenge #14: Probe for hidden/undeclared resources
38
+ * Tests common hidden resource patterns to find accessible but undeclared resources
39
+ */
40
+ private testHiddenResourceDiscovery;
41
+ /**
42
+ * Helper: Probe a single hidden resource URI
43
+ */
44
+ private probeHiddenResource;
31
45
  private isValidUri;
32
46
  private isValidUriTemplate;
33
47
  private isSensitiveUri;
@@ -1 +1 @@
1
- {"version":3,"file":"ResourceAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ResourceAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,kBAAkB,EAGnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAoN9D,qBAAa,gBAAiB,SAAQ,YAAY;IAC1C,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAgFrE,OAAO,CAAC,yBAAyB;YAiBnB,YAAY;IAoG1B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA4B3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;YAsBjB,oBAAoB;IAkGlC,OAAO,CAAC,UAAU;IAsBlB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,wBAAwB;IAIhC;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,uBAAuB;IAqB/B,OAAO,CAAC,mBAAmB;IAoC3B,OAAO,CAAC,uBAAuB;CA+DhC"}
1
+ {"version":3,"file":"ResourceAssessor.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/modules/ResourceAssessor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,kBAAkB,EAGnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAuQ9D,qBAAa,gBAAiB,SAAQ,YAAY;IAC1C,MAAM,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA8FrE,OAAO,CAAC,yBAAyB;YAiBnB,YAAY;IAoG1B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA4B3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;YAsBjB,oBAAoB;IAkGlC;;;OAGG;YACW,6BAA6B;IA4F3C;;;OAGG;YACW,2BAA2B;IAgEzC;;OAEG;YACW,mBAAmB;IAmEjC,OAAO,CAAC,UAAU;IAsBlB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,wBAAwB;IAIhC;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,uBAAuB;IAqB/B,OAAO,CAAC,mBAAmB;IAoC3B,OAAO,CAAC,uBAAuB;CA+DhC"}