@bryan-thompson/inspector-assessment-client 1.11.1 → 1.13.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 (30) hide show
  1. package/dist/assets/{OAuthCallback-DA2koy6X.js → OAuthCallback-D8KW6pFf.js} +1 -1
  2. package/dist/assets/{OAuthDebugCallback-Bx60PQTT.js → OAuthDebugCallback-D15nNAOl.js} +1 -1
  3. package/dist/assets/{index-kJ0jPd4m.js → index-cVkEgqCc.js} +130 -5
  4. package/dist/index.html +1 -1
  5. package/lib/lib/assessmentTypes.d.ts +72 -1
  6. package/lib/lib/assessmentTypes.d.ts.map +1 -1
  7. package/lib/lib/policyMapping.d.ts +183 -0
  8. package/lib/lib/policyMapping.d.ts.map +1 -0
  9. package/lib/lib/policyMapping.js +442 -0
  10. package/lib/lib/reportFormatters/MarkdownReportFormatter.d.ts +91 -0
  11. package/lib/lib/reportFormatters/MarkdownReportFormatter.d.ts.map +1 -0
  12. package/lib/lib/reportFormatters/MarkdownReportFormatter.js +498 -0
  13. package/lib/lib/reportFormatters/index.d.ts +50 -0
  14. package/lib/lib/reportFormatters/index.d.ts.map +1 -0
  15. package/lib/lib/reportFormatters/index.js +81 -0
  16. package/lib/lib/securityPatterns.d.ts +3 -3
  17. package/lib/lib/securityPatterns.d.ts.map +1 -1
  18. package/lib/lib/securityPatterns.js +129 -4
  19. package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
  20. package/lib/services/assessment/AssessmentOrchestrator.js +8 -0
  21. package/lib/services/assessment/PolicyComplianceGenerator.d.ts +119 -0
  22. package/lib/services/assessment/PolicyComplianceGenerator.d.ts.map +1 -0
  23. package/lib/services/assessment/PolicyComplianceGenerator.js +632 -0
  24. package/lib/services/assessment/config/annotationPatterns.d.ts +70 -0
  25. package/lib/services/assessment/config/annotationPatterns.d.ts.map +1 -0
  26. package/lib/services/assessment/config/annotationPatterns.js +305 -0
  27. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +22 -2
  28. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -1
  29. package/lib/services/assessment/modules/ToolAnnotationAssessor.js +289 -152
  30. package/package.json +1 -1
@@ -0,0 +1,632 @@
1
+ /**
2
+ * Policy Compliance Generator
3
+ *
4
+ * Maps MCP Inspector assessment results to Anthropic's Software Directory
5
+ * Policy requirements (30 total). Generates a structured compliance report
6
+ * that can be used for directory submission review.
7
+ *
8
+ * @module PolicyComplianceGenerator
9
+ */
10
+ import { ANTHROPIC_POLICY_REQUIREMENTS, getCategoryDisplayName, } from "../../lib/policyMapping.js";
11
+ /**
12
+ * Generator for policy compliance reports
13
+ */
14
+ export class PolicyComplianceGenerator {
15
+ version;
16
+ constructor(version = "1.0.0") {
17
+ this.version = version;
18
+ }
19
+ /**
20
+ * Generate a full policy compliance report from assessment results
21
+ */
22
+ generate(assessment, serverName) {
23
+ const results = this.evaluateAllRequirements(assessment);
24
+ const byCategory = this.groupByCategory(results);
25
+ const summary = this.calculateSummary(results);
26
+ const criticalIssues = this.identifyCriticalIssues(results);
27
+ const actionItems = this.generateActionItems(results);
28
+ return {
29
+ serverName: serverName || assessment.serverName,
30
+ generatedAt: new Date().toISOString(),
31
+ assessorVersion: this.version,
32
+ summary,
33
+ byCategory,
34
+ criticalIssues,
35
+ actionItems,
36
+ sourceAssessment: {
37
+ totalTestsRun: assessment.totalTestsRun,
38
+ executionTime: assessment.executionTime,
39
+ modulesRun: this.getRunModules(assessment),
40
+ },
41
+ };
42
+ }
43
+ /**
44
+ * Evaluate all 30 policy requirements against assessment results
45
+ */
46
+ evaluateAllRequirements(assessment) {
47
+ return ANTHROPIC_POLICY_REQUIREMENTS.map((req) => this.evaluateRequirement(req, assessment));
48
+ }
49
+ /**
50
+ * Evaluate a single policy requirement
51
+ */
52
+ evaluateRequirement(requirement, assessment) {
53
+ const evidence = [];
54
+ const moduleResults = [];
55
+ // Collect evidence from each source module
56
+ for (const moduleName of requirement.moduleSource) {
57
+ const moduleData = this.getModuleData(assessment, moduleName);
58
+ if (moduleData) {
59
+ const findings = this.extractRelevantFindings(moduleName, moduleData, requirement.id);
60
+ moduleResults.push({
61
+ module: moduleName,
62
+ status: moduleData.status || "UNKNOWN",
63
+ relevantFindings: findings,
64
+ });
65
+ evidence.push(...findings);
66
+ }
67
+ }
68
+ // Determine compliance status
69
+ const status = this.determineComplianceStatus(requirement, moduleResults, evidence);
70
+ // Generate recommendation if needed
71
+ const recommendation = status !== "PASS" && status !== "NOT_APPLICABLE"
72
+ ? this.generateRecommendation(requirement, status, evidence)
73
+ : undefined;
74
+ // Determine if manual review is required
75
+ const manualReviewRequired = !requirement.automatable ||
76
+ status === "FLAG" ||
77
+ status === "REVIEW" ||
78
+ status === "NOT_TESTED";
79
+ return {
80
+ requirement,
81
+ status,
82
+ evidence,
83
+ moduleResults,
84
+ recommendation,
85
+ manualReviewRequired,
86
+ manualReviewGuidance: manualReviewRequired
87
+ ? this.getManualReviewGuidance(requirement, status)
88
+ : undefined,
89
+ };
90
+ }
91
+ /**
92
+ * Get module data from assessment by module name
93
+ */
94
+ getModuleData(assessment, moduleName) {
95
+ const moduleMap = {
96
+ aupCompliance: assessment.aupCompliance,
97
+ security: assessment.security,
98
+ functionality: assessment.functionality,
99
+ errorHandling: assessment.errorHandling,
100
+ usability: assessment.usability,
101
+ documentation: assessment.documentation,
102
+ mcpSpecCompliance: assessment.mcpSpecCompliance,
103
+ toolAnnotations: assessment.toolAnnotations,
104
+ prohibitedLibraries: assessment.prohibitedLibraries,
105
+ manifestValidation: assessment.manifestValidation,
106
+ portability: assessment.portability,
107
+ };
108
+ const data = moduleMap[moduleName];
109
+ if (data && typeof data === "object") {
110
+ return data;
111
+ }
112
+ return null;
113
+ }
114
+ /**
115
+ * Extract relevant findings from a module for a specific requirement
116
+ */
117
+ extractRelevantFindings(moduleName, moduleData, requirementId) {
118
+ const findings = [];
119
+ // Extract based on module type
120
+ switch (moduleName) {
121
+ case "aupCompliance":
122
+ findings.push(...this.extractAUPFindings(moduleData, requirementId));
123
+ break;
124
+ case "security":
125
+ findings.push(...this.extractSecurityFindings(moduleData, requirementId));
126
+ break;
127
+ case "functionality":
128
+ findings.push(...this.extractFunctionalityFindings(moduleData, requirementId));
129
+ break;
130
+ case "errorHandling":
131
+ findings.push(...this.extractErrorHandlingFindings(moduleData, requirementId));
132
+ break;
133
+ case "toolAnnotations":
134
+ findings.push(...this.extractToolAnnotationFindings(moduleData, requirementId));
135
+ break;
136
+ case "documentation":
137
+ findings.push(...this.extractDocumentationFindings(moduleData, requirementId));
138
+ break;
139
+ case "mcpSpecCompliance":
140
+ findings.push(...this.extractMCPSpecFindings(moduleData, requirementId));
141
+ break;
142
+ case "prohibitedLibraries":
143
+ findings.push(...this.extractProhibitedLibraryFindings(moduleData, requirementId));
144
+ break;
145
+ case "manifestValidation":
146
+ findings.push(...this.extractManifestFindings(moduleData, requirementId));
147
+ break;
148
+ case "portability":
149
+ findings.push(...this.extractPortabilityFindings(moduleData, requirementId));
150
+ break;
151
+ default:
152
+ // Generic extraction
153
+ if (moduleData.status) {
154
+ findings.push(`${moduleName} status: ${moduleData.status}`);
155
+ }
156
+ }
157
+ return findings;
158
+ }
159
+ /**
160
+ * Extract AUP compliance findings
161
+ */
162
+ extractAUPFindings(data, requirementId) {
163
+ const findings = [];
164
+ if (data.status) {
165
+ findings.push(`AUP compliance status: ${data.status}`);
166
+ }
167
+ // Check for violations
168
+ const violations = data.violations;
169
+ if (Array.isArray(violations) && violations.length > 0) {
170
+ const violationCount = violations.length;
171
+ findings.push(`${violationCount} AUP violation(s) detected`);
172
+ // Add specific violation categories
173
+ if (requirementId.startsWith("SAFETY-")) {
174
+ const critical = violations.filter((v) => typeof v === "object" && v !== null && "severity" in v);
175
+ if (critical.length > 0) {
176
+ findings.push(`${critical.length} critical safety violation(s)`);
177
+ }
178
+ }
179
+ }
180
+ // Check overall score
181
+ const score = data.overallScore;
182
+ if (typeof score === "number") {
183
+ findings.push(`AUP compliance score: ${score}%`);
184
+ }
185
+ return findings;
186
+ }
187
+ /**
188
+ * Extract security findings
189
+ */
190
+ extractSecurityFindings(data, _requirementId) {
191
+ const findings = [];
192
+ if (data.status) {
193
+ findings.push(`Security assessment status: ${data.status}`);
194
+ }
195
+ // Check for vulnerabilities
196
+ const vulnerabilities = data.vulnerabilities;
197
+ if (Array.isArray(vulnerabilities)) {
198
+ if (vulnerabilities.length === 0) {
199
+ findings.push("No security vulnerabilities detected");
200
+ }
201
+ else {
202
+ findings.push(`${vulnerabilities.length} security vulnerability(ies) detected`);
203
+ }
204
+ }
205
+ // Check for prompt injection tests
206
+ const promptTests = data.promptInjectionTests;
207
+ if (Array.isArray(promptTests)) {
208
+ const vulnerable = promptTests.filter((t) => typeof t === "object" &&
209
+ t !== null &&
210
+ t.vulnerable);
211
+ if (vulnerable.length > 0) {
212
+ findings.push(`${vulnerable.length} tool(s) vulnerable to injection`);
213
+ }
214
+ }
215
+ return findings;
216
+ }
217
+ /**
218
+ * Extract functionality findings
219
+ */
220
+ extractFunctionalityFindings(data, _requirementId) {
221
+ const findings = [];
222
+ if (data.status) {
223
+ findings.push(`Functionality status: ${data.status}`);
224
+ }
225
+ // Check working/broken tools
226
+ const workingTools = data.workingTools;
227
+ const brokenTools = data.brokenTools;
228
+ if (Array.isArray(workingTools)) {
229
+ findings.push(`${workingTools.length} tool(s) working correctly`);
230
+ }
231
+ if (Array.isArray(brokenTools) && brokenTools.length > 0) {
232
+ findings.push(`${brokenTools.length} tool(s) with issues`);
233
+ }
234
+ // Check overall success rate
235
+ const summary = data.summary;
236
+ if (typeof summary === "object" && summary !== null) {
237
+ const s = summary;
238
+ if (typeof s.successRate === "number") {
239
+ findings.push(`Tool success rate: ${s.successRate.toFixed(1)}%`);
240
+ }
241
+ }
242
+ return findings;
243
+ }
244
+ /**
245
+ * Extract error handling findings
246
+ */
247
+ extractErrorHandlingFindings(data, _requirementId) {
248
+ const findings = [];
249
+ if (data.status) {
250
+ findings.push(`Error handling status: ${data.status}`);
251
+ }
252
+ const metrics = data.metrics;
253
+ if (typeof metrics === "object" && metrics !== null) {
254
+ if (typeof metrics.totalTests === "number") {
255
+ findings.push(`${metrics.totalTests} error handling tests executed`);
256
+ }
257
+ if (typeof metrics.passRate === "number") {
258
+ findings.push(`Error handling pass rate: ${metrics.passRate}%`);
259
+ }
260
+ }
261
+ return findings;
262
+ }
263
+ /**
264
+ * Extract tool annotation findings
265
+ */
266
+ extractToolAnnotationFindings(data, _requirementId) {
267
+ const findings = [];
268
+ if (data.status) {
269
+ findings.push(`Tool annotations status: ${data.status}`);
270
+ }
271
+ // Check annotation coverage
272
+ const annotatedCount = data.annotatedCount;
273
+ const missingCount = data.missingAnnotationsCount;
274
+ const misalignedCount = data.misalignedAnnotationsCount;
275
+ if (typeof annotatedCount === "number") {
276
+ findings.push(`${annotatedCount} tool(s) with annotations`);
277
+ }
278
+ if (typeof missingCount === "number" && missingCount > 0) {
279
+ findings.push(`${missingCount} tool(s) missing annotations`);
280
+ }
281
+ if (typeof misalignedCount === "number" && misalignedCount > 0) {
282
+ findings.push(`${misalignedCount} tool(s) with misaligned annotations`);
283
+ }
284
+ // Check annotation sources
285
+ const sources = data.annotationSources;
286
+ if (typeof sources === "object" && sources !== null) {
287
+ if (sources.mcp > 0) {
288
+ findings.push(`${sources.mcp} tool(s) with MCP protocol annotations`);
289
+ }
290
+ }
291
+ return findings;
292
+ }
293
+ /**
294
+ * Extract documentation findings
295
+ */
296
+ extractDocumentationFindings(data, _requirementId) {
297
+ const findings = [];
298
+ if (data.status) {
299
+ findings.push(`Documentation status: ${data.status}`);
300
+ }
301
+ // Check documentation quality
302
+ const quality = data.quality;
303
+ if (typeof quality === "object" && quality !== null) {
304
+ if (typeof quality.overallScore === "number") {
305
+ findings.push(`Documentation quality score: ${quality.overallScore}%`);
306
+ }
307
+ }
308
+ return findings;
309
+ }
310
+ /**
311
+ * Extract MCP spec compliance findings
312
+ */
313
+ extractMCPSpecFindings(data, _requirementId) {
314
+ const findings = [];
315
+ if (data.status) {
316
+ findings.push(`MCP spec compliance status: ${data.status}`);
317
+ }
318
+ // Check protocol compliance
319
+ const summary = data.summary;
320
+ if (typeof summary === "object" && summary !== null) {
321
+ if (typeof summary.totalChecks === "number") {
322
+ findings.push(`${summary.totalChecks} protocol checks performed`);
323
+ }
324
+ }
325
+ return findings;
326
+ }
327
+ /**
328
+ * Extract prohibited library findings
329
+ */
330
+ extractProhibitedLibraryFindings(data, _requirementId) {
331
+ const findings = [];
332
+ if (data.status) {
333
+ findings.push(`Prohibited libraries status: ${data.status}`);
334
+ }
335
+ const detected = data.prohibitedLibrariesDetected;
336
+ if (Array.isArray(detected)) {
337
+ if (detected.length === 0) {
338
+ findings.push("No prohibited libraries detected");
339
+ }
340
+ else {
341
+ findings.push(`${detected.length} prohibited library(ies) detected`);
342
+ }
343
+ }
344
+ return findings;
345
+ }
346
+ /**
347
+ * Extract manifest findings
348
+ */
349
+ extractManifestFindings(data, _requirementId) {
350
+ const findings = [];
351
+ if (data.status) {
352
+ findings.push(`Manifest validation status: ${data.status}`);
353
+ }
354
+ const valid = data.isValid;
355
+ if (typeof valid === "boolean") {
356
+ findings.push(valid ? "Manifest is valid" : "Manifest validation failed");
357
+ }
358
+ return findings;
359
+ }
360
+ /**
361
+ * Extract portability findings
362
+ */
363
+ extractPortabilityFindings(data, _requirementId) {
364
+ const findings = [];
365
+ if (data.status) {
366
+ findings.push(`Portability status: ${data.status}`);
367
+ }
368
+ const issues = data.issues;
369
+ if (Array.isArray(issues)) {
370
+ if (issues.length === 0) {
371
+ findings.push("No portability issues detected");
372
+ }
373
+ else {
374
+ findings.push(`${issues.length} portability issue(s) detected`);
375
+ }
376
+ }
377
+ return findings;
378
+ }
379
+ /**
380
+ * Determine compliance status based on module results and evidence
381
+ */
382
+ determineComplianceStatus(requirement, moduleResults, evidence) {
383
+ // If no modules were run, mark as NOT_TESTED
384
+ if (moduleResults.length === 0) {
385
+ return "NOT_TESTED";
386
+ }
387
+ // Check if all modules passed
388
+ const allPassed = moduleResults.every((r) => r.status === "PASS" || r.status === "NEED_MORE_INFO");
389
+ const anyFailed = moduleResults.some((r) => r.status === "FAIL");
390
+ const anyNeedInfo = moduleResults.some((r) => r.status === "NEED_MORE_INFO");
391
+ // Check for critical findings in evidence
392
+ const hasCriticalFindings = evidence.some((e) => e.toLowerCase().includes("critical") ||
393
+ e.toLowerCase().includes("vulnerability") ||
394
+ e.toLowerCase().includes("violation"));
395
+ // Determine status based on severity and findings
396
+ if (anyFailed) {
397
+ if (requirement.severity === "CRITICAL" || hasCriticalFindings) {
398
+ return "FAIL";
399
+ }
400
+ return "FLAG";
401
+ }
402
+ if (anyNeedInfo) {
403
+ return "REVIEW";
404
+ }
405
+ if (allPassed && !hasCriticalFindings) {
406
+ return "PASS";
407
+ }
408
+ // Default to review if unclear
409
+ return "REVIEW";
410
+ }
411
+ /**
412
+ * Generate a recommendation for non-passing requirements
413
+ */
414
+ generateRecommendation(requirement, status, evidence) {
415
+ const prefix = status === "FAIL"
416
+ ? "[REQUIRED]"
417
+ : status === "FLAG"
418
+ ? "[RECOMMENDED]"
419
+ : "[REVIEW]";
420
+ // Generate specific recommendations based on requirement
421
+ const recommendations = {
422
+ "SAFETY-1": "Ensure server complies with Anthropic's Acceptable Use Policy",
423
+ "SAFETY-2": "Fix security vulnerabilities before submission",
424
+ "SAFETY-3": "Remove any malicious or deceptive functionality",
425
+ "SAFETY-4": "Implement proper input validation and sanitization",
426
+ "SAFETY-5": "Secure sensitive data handling and storage",
427
+ "SAFETY-6": "Implement proper authentication and authorization",
428
+ "COMPAT-1": "Ensure full MCP protocol compliance",
429
+ "COMPAT-2": "Support required MCP message types",
430
+ "COMPAT-3": "Remove or replace prohibited dependencies",
431
+ "COMPAT-4": "Fix compatibility issues with Claude clients",
432
+ "COMPAT-5": "Test across supported platforms",
433
+ "COMPAT-6": "Ensure cross-platform portability",
434
+ "FUNC-1": "Ensure all tools function as documented",
435
+ "FUNC-2": "Improve tool reliability and consistency",
436
+ "FUNC-3": "Implement proper error handling",
437
+ "FUNC-4": "Improve tool documentation",
438
+ "FUNC-5": "Add required tool annotations (readOnlyHint, destructiveHint)",
439
+ "FUNC-6": "Ensure tools produce meaningful results",
440
+ "FUNC-7": "Improve usability and user experience",
441
+ "DEV-1": "Provide valid manifest.json",
442
+ "DEV-2": "Include license information",
443
+ "DEV-3": "Add comprehensive README documentation",
444
+ "DEV-4": "Provide installation instructions",
445
+ "DEV-5": "Include usage examples",
446
+ "DEV-6": "Document configuration options",
447
+ "DEV-7": "Add contribution guidelines",
448
+ "DEV-8": "Maintain changelog",
449
+ "UNSUPP-1": "Remove cryptocurrency/blockchain functionality",
450
+ "UNSUPP-2": "Remove gambling functionality",
451
+ "UNSUPP-3": "Remove adult content functionality",
452
+ };
453
+ const baseRec = recommendations[requirement.id] || `Address ${requirement.name} issues`;
454
+ // Add evidence-specific context if available
455
+ const relevantEvidence = evidence.slice(0, 2).join("; ");
456
+ if (relevantEvidence) {
457
+ return `${prefix} ${baseRec}. Evidence: ${relevantEvidence}`;
458
+ }
459
+ return `${prefix} ${baseRec}`;
460
+ }
461
+ /**
462
+ * Get manual review guidance for a requirement
463
+ */
464
+ getManualReviewGuidance(requirement, status) {
465
+ if (status === "NOT_TESTED") {
466
+ return `Run the following assessment modules to evaluate this requirement: ${requirement.moduleSource.join(", ")}`;
467
+ }
468
+ if (status === "FLAG" || status === "REVIEW") {
469
+ return `Manually verify: ${requirement.description}. Automated assessment found potential issues that require human judgment.`;
470
+ }
471
+ return `Review ${requirement.name} manually as this requirement cannot be fully automated.`;
472
+ }
473
+ /**
474
+ * Group results by category
475
+ */
476
+ groupByCategory(results) {
477
+ const categories = [
478
+ "safety_security",
479
+ "compatibility",
480
+ "functionality",
481
+ "developer_requirements",
482
+ "unsupported_use_cases",
483
+ ];
484
+ const byCategory = {};
485
+ for (const category of categories) {
486
+ const categoryResults = results.filter((r) => r.requirement.category === category);
487
+ const passed = categoryResults.filter((r) => r.status === "PASS").length;
488
+ const failed = categoryResults.filter((r) => r.status === "FAIL" || r.status === "FLAG").length;
489
+ let categoryStatus = "PASS";
490
+ if (failed > 0) {
491
+ const hasCriticalFail = categoryResults.some((r) => r.status === "FAIL" && r.requirement.severity === "CRITICAL");
492
+ categoryStatus = hasCriticalFail ? "FAIL" : "FLAG";
493
+ }
494
+ else if (categoryResults.some((r) => r.status === "REVIEW")) {
495
+ categoryStatus = "REVIEW";
496
+ }
497
+ else if (categoryResults.every((r) => r.status === "NOT_TESTED")) {
498
+ categoryStatus = "NOT_TESTED";
499
+ }
500
+ byCategory[category] = {
501
+ category,
502
+ categoryName: getCategoryDisplayName(category),
503
+ total: categoryResults.length,
504
+ passed,
505
+ failed,
506
+ status: categoryStatus,
507
+ requirements: categoryResults,
508
+ };
509
+ }
510
+ return byCategory;
511
+ }
512
+ /**
513
+ * Calculate summary statistics
514
+ */
515
+ calculateSummary(results) {
516
+ const passed = results.filter((r) => r.status === "PASS").length;
517
+ const failed = results.filter((r) => r.status === "FAIL").length;
518
+ const flagged = results.filter((r) => r.status === "FLAG").length;
519
+ const needsReview = results.filter((r) => r.status === "REVIEW").length;
520
+ const notApplicable = results.filter((r) => r.status === "NOT_APPLICABLE").length;
521
+ const notTested = results.filter((r) => r.status === "NOT_TESTED").length;
522
+ const applicableTotal = results.length - notApplicable - notTested;
523
+ const complianceScore = applicableTotal > 0 ? Math.round((passed / applicableTotal) * 100) : 0;
524
+ // Determine overall status
525
+ let overallStatus = "COMPLIANT";
526
+ if (failed > 0) {
527
+ // Check if any critical requirements failed
528
+ const criticalFailed = results.some((r) => r.status === "FAIL" && r.requirement.severity === "CRITICAL");
529
+ overallStatus = criticalFailed ? "NON_COMPLIANT" : "NEEDS_REVIEW";
530
+ }
531
+ else if (flagged > 0 || needsReview > 0) {
532
+ overallStatus = "NEEDS_REVIEW";
533
+ }
534
+ return {
535
+ totalRequirements: results.length,
536
+ passed,
537
+ failed,
538
+ flagged,
539
+ needsReview,
540
+ notApplicable,
541
+ notTested,
542
+ complianceScore,
543
+ overallStatus,
544
+ };
545
+ }
546
+ /**
547
+ * Identify critical issues
548
+ */
549
+ identifyCriticalIssues(results) {
550
+ return results.filter((r) => (r.status === "FAIL" || r.status === "FLAG") &&
551
+ (r.requirement.severity === "CRITICAL" ||
552
+ r.requirement.severity === "HIGH"));
553
+ }
554
+ /**
555
+ * Generate prioritized action items
556
+ */
557
+ generateActionItems(results) {
558
+ const actionItems = [];
559
+ // Group by severity
560
+ const critical = results.filter((r) => r.status === "FAIL" && r.requirement.severity === "CRITICAL");
561
+ const high = results.filter((r) => (r.status === "FAIL" && r.requirement.severity === "HIGH") ||
562
+ (r.status === "FLAG" && r.requirement.severity === "CRITICAL"));
563
+ const medium = results.filter((r) => (r.status === "FAIL" && r.requirement.severity === "MEDIUM") ||
564
+ (r.status === "FLAG" && r.requirement.severity === "HIGH"));
565
+ // Add critical items first
566
+ for (const result of critical) {
567
+ if (result.recommendation) {
568
+ actionItems.push(`[CRITICAL] ${result.recommendation}`);
569
+ }
570
+ }
571
+ // Add high priority items
572
+ for (const result of high) {
573
+ if (result.recommendation) {
574
+ actionItems.push(`[HIGH] ${result.recommendation}`);
575
+ }
576
+ }
577
+ // Add medium priority items (limit to avoid overwhelming)
578
+ for (const result of medium.slice(0, 5)) {
579
+ if (result.recommendation) {
580
+ actionItems.push(`[MEDIUM] ${result.recommendation}`);
581
+ }
582
+ }
583
+ // Add review items summary if many exist
584
+ const reviewCount = results.filter((r) => r.status === "REVIEW" || r.status === "NOT_TESTED").length;
585
+ if (reviewCount > 0) {
586
+ actionItems.push(`[INFO] ${reviewCount} requirement(s) need manual review or additional testing`);
587
+ }
588
+ return actionItems;
589
+ }
590
+ /**
591
+ * Get list of modules that were run in the assessment
592
+ */
593
+ getRunModules(assessment) {
594
+ const modules = [];
595
+ if (assessment.functionality)
596
+ modules.push("functionality");
597
+ if (assessment.security)
598
+ modules.push("security");
599
+ if (assessment.documentation)
600
+ modules.push("documentation");
601
+ if (assessment.errorHandling)
602
+ modules.push("errorHandling");
603
+ if (assessment.usability)
604
+ modules.push("usability");
605
+ if (assessment.mcpSpecCompliance)
606
+ modules.push("mcpSpecCompliance");
607
+ if (assessment.aupCompliance)
608
+ modules.push("aupCompliance");
609
+ if (assessment.toolAnnotations)
610
+ modules.push("toolAnnotations");
611
+ if (assessment.prohibitedLibraries)
612
+ modules.push("prohibitedLibraries");
613
+ if (assessment.manifestValidation)
614
+ modules.push("manifestValidation");
615
+ if (assessment.portability)
616
+ modules.push("portability");
617
+ return modules;
618
+ }
619
+ }
620
+ /**
621
+ * Factory function to create a policy compliance generator
622
+ */
623
+ export function createPolicyComplianceGenerator(version) {
624
+ return new PolicyComplianceGenerator(version);
625
+ }
626
+ /**
627
+ * Quick utility to generate a compliance report
628
+ */
629
+ export function generatePolicyComplianceReport(assessment, serverName) {
630
+ const generator = createPolicyComplianceGenerator();
631
+ return generator.generate(assessment, serverName);
632
+ }