framework-mcp 1.1.0 → 1.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "framework-mcp",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "MCP server for analyzing vendor responses against CIS Controls Framework using 4 GRC attributes (Governance, Facilitates, Coverage, Validates)",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
package/src/index.ts CHANGED
@@ -84,6 +84,65 @@ interface AnalysisResult {
84
84
  recommendations: string[];
85
85
  }
86
86
 
87
+ interface ValidationResult {
88
+ vendor: string;
89
+ safeguard_id: string;
90
+ safeguard_title: string;
91
+ claimed_capability: string;
92
+ validation_status: 'SUPPORTED' | 'QUESTIONABLE' | 'UNSUPPORTED';
93
+ confidence_score: number; // 0-100
94
+ evidence_analysis: {
95
+ core_requirements_coverage: number;
96
+ sub_elements_coverage: number;
97
+ governance_alignment: number;
98
+ language_consistency: number;
99
+ };
100
+ domain_validation: {
101
+ required_tool_type: string;
102
+ detected_tool_type: string;
103
+ domain_match: boolean;
104
+ capability_adjusted: boolean;
105
+ original_claim?: string;
106
+ };
107
+ gaps_identified: string[];
108
+ strengths_identified: string[];
109
+ recommendations: string[];
110
+ detailed_feedback: string;
111
+ }
112
+
113
+ // Domain-specific validation mapping
114
+ const SAFEGUARD_DOMAIN_REQUIREMENTS: Record<string, {
115
+ domain: string;
116
+ required_tool_types: string[];
117
+ description: string;
118
+ }> = {
119
+ "1.1": {
120
+ domain: "Asset Inventory",
121
+ required_tool_types: ["inventory", "asset_management", "cmdb", "discovery"],
122
+ description: "Only asset inventory and discovery tools can provide FULL/PARTIAL coverage"
123
+ },
124
+ "1.2": {
125
+ domain: "Asset Management",
126
+ required_tool_types: ["inventory", "asset_management", "network_security", "nac"],
127
+ description: "Asset management or network access control tools required for FULL/PARTIAL"
128
+ },
129
+ "5.1": {
130
+ domain: "Account Management",
131
+ required_tool_types: ["identity_management", "iam", "directory", "account_management"],
132
+ description: "Identity and account management tools required for FULL/PARTIAL"
133
+ },
134
+ "6.3": {
135
+ domain: "Authentication",
136
+ required_tool_types: ["mfa", "authentication", "identity_management", "iam"],
137
+ description: "Multi-factor authentication and identity tools required for FULL/PARTIAL"
138
+ },
139
+ "7.1": {
140
+ domain: "Vulnerability Management",
141
+ required_tool_types: ["vulnerability_management", "vulnerability_scanner", "patch_management"],
142
+ description: "Vulnerability management and scanning tools required for FULL/PARTIAL"
143
+ }
144
+ };
145
+
87
146
  // Enhanced CIS Controls Framework Data with color-coded categorization
88
147
  const CIS_SAFEGUARDS: Record<string, SafeguardElement> = {
89
148
  "1.1": {
@@ -5633,6 +5692,35 @@ export class GRCAnalysisServer {
5633
5692
  }
5634
5693
  }
5635
5694
  }
5695
+ } as Tool,
5696
+ {
5697
+ name: 'validate_vendor_mapping',
5698
+ description: 'Validate whether a vendor\'s stated capability mapping (Full/Partial/Facilitates/Governance/Validates) is actually supported by their explanatory text for a specific CIS safeguard',
5699
+ inputSchema: {
5700
+ type: 'object',
5701
+ properties: {
5702
+ vendor_name: {
5703
+ type: 'string',
5704
+ description: 'Name of the vendor (optional)',
5705
+ default: 'Unknown Vendor'
5706
+ },
5707
+ safeguard_id: {
5708
+ type: 'string',
5709
+ description: 'CIS Control safeguard ID (e.g., "5.1", "1.1", "6.3")',
5710
+ pattern: '^[0-9]+\\.[0-9]+$'
5711
+ },
5712
+ claimed_capability: {
5713
+ type: 'string',
5714
+ enum: ['full', 'partial', 'facilitates', 'governance', 'validates'],
5715
+ description: 'Vendor\'s claimed capability mapping for this safeguard'
5716
+ },
5717
+ supporting_text: {
5718
+ type: 'string',
5719
+ description: 'Vendor\'s supporting text blob explaining how they meet the claimed capability'
5720
+ }
5721
+ },
5722
+ required: ['safeguard_id', 'claimed_capability', 'supporting_text']
5723
+ }
5636
5724
  } as Tool
5637
5725
  ],
5638
5726
  }));
@@ -5650,6 +5738,8 @@ export class GRCAnalysisServer {
5650
5738
  return await this.validateCoverageClaim(args);
5651
5739
  case 'list_available_safeguards':
5652
5740
  return await this.listAvailableSafeguards(args);
5741
+ case 'validate_vendor_mapping':
5742
+ return await this.validateVendorMapping(args);
5653
5743
  default:
5654
5744
  throw new Error(`Unknown tool: ${name}`);
5655
5745
  }
@@ -5817,6 +5907,11 @@ export class GRCAnalysisServer {
5817
5907
  'improve', 'enhance', 'optimize', 'faster', 'better', 'stronger', 'automate',
5818
5908
  'streamline', 'efficiency', 'facilitate', 'support', 'enable', 'accelerate',
5819
5909
  'api', 'integration', 'data', 'export', 'import', 'sync', 'feed',
5910
+ // Data provision and enrichment
5911
+ 'provides data', 'data source', 'data feeds', 'enrichment', 'data enrichment',
5912
+ 'supplemental data', 'additional data', 'contextual data', 'threat data',
5913
+ 'intelligence feeds', 'data aggregation', 'data collection', 'data gathering',
5914
+ 'feeds data', 'populates', 'informs', 'enriches', 'supplements',
5820
5915
  // Governance/process facilitation (new keywords for tools like Upolicy)
5821
5916
  'enables compliance', 'facilitates implementation', 'supports compliance',
5822
5917
  'creates framework', 'enables organizations', 'infrastructure', 'foundation',
@@ -5827,9 +5922,9 @@ export class GRCAnalysisServer {
5827
5922
 
5828
5923
  const validatesKeywords = [
5829
5924
  'audit', 'report', 'evidence', 'verify', 'validate', 'check', 'monitor',
5830
- 'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest',
5925
+ 'compliance', 'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest',
5831
5926
  'dashboard', 'metrics', 'analytics', 'visibility', 'alert', 'attestation',
5832
- 'compliance tracking', 'audit trail', 'reporting capabilities'
5927
+ 'compliance tracking', 'audit trail', 'reporting capabilities', 'audit capabilities'
5833
5928
  ];
5834
5929
 
5835
5930
  // Analyze element coverage (binary: covered or not)
@@ -5865,19 +5960,25 @@ export class GRCAnalysisServer {
5865
5960
  ];
5866
5961
  const hasNonImplementationLanguage = nonImplementationPatterns.some(pattern => text.includes(pattern));
5867
5962
 
5868
- // Determine if full or partial coverage (based on core + sub-taxonomical elements)
5869
- const totalCoreAndSubElements = safeguard.coreRequirements.length + safeguard.subTaxonomicalElements.length;
5870
- const coveredCoreAndSubElements = coreCoverage.coveredElements.length + subElementCoverage.coveredElements.length;
5963
+ // Determine if full or partial coverage (based on core + sub-taxonomical elements WITHIN SCOPE)
5964
+ // Full = addresses majority of core requirements + substantial sub-elements within their stated scope
5965
+ // Partial = addresses some core requirements with clear scope boundaries
5966
+
5967
+ const corePercentage = safeguard.coreRequirements.length > 0 ?
5968
+ (coreCoverage.coveredElements.length / safeguard.coreRequirements.length) * 100 : 0;
5969
+ const subElementPercentage = safeguard.subTaxonomicalElements.length > 0 ?
5970
+ (subElementCoverage.coveredElements.length / safeguard.subTaxonomicalElements.length) * 100 : 0;
5871
5971
 
5872
5972
  let fullCapability = false;
5873
5973
  let partialCapability = false;
5874
5974
 
5875
- if (totalCoreAndSubElements > 0) {
5876
- if (coveredCoreAndSubElements === totalCoreAndSubElements) {
5877
- fullCapability = true;
5878
- } else if (coveredCoreAndSubElements > 0) {
5879
- partialCapability = true;
5880
- }
5975
+ // Full capability: High coverage of core requirements + reasonable sub-element coverage
5976
+ if (corePercentage >= 70 && subElementPercentage >= 50) {
5977
+ fullCapability = true;
5978
+ }
5979
+ // Partial capability: Moderate core coverage OR clear scope-limited implementation
5980
+ else if (corePercentage >= 30 || (coreCoverage.coveredElements.length > 0 && subElementPercentage >= 20)) {
5981
+ partialCapability = true;
5881
5982
  }
5882
5983
 
5883
5984
  // Enhanced primary capability logic
@@ -5914,6 +6015,8 @@ export class GRCAnalysisServer {
5914
6015
  // Calculate confidence based on evidence strength and keyword matches
5915
6016
  const keywordConfidence = (governanceScore + facilitatesScore + validatesScore) / 3;
5916
6017
 
6018
+ const totalCoreAndSubElements = safeguard.coreRequirements.length + safeguard.subTaxonomicalElements.length;
6019
+ const coveredCoreAndSubElements = coreCoverage.coveredElements.length + subElementCoverage.coveredElements.length;
5917
6020
  const coverageConfidence = totalCoreAndSubElements > 0 ?
5918
6021
  coveredCoreAndSubElements / totalCoreAndSubElements : 0;
5919
6022
 
@@ -6262,6 +6365,473 @@ export class GRCAnalysisServer {
6262
6365
  return validation;
6263
6366
  }
6264
6367
 
6368
+ private async validateVendorMapping(args: any) {
6369
+ const { vendor_name = 'Unknown Vendor', safeguard_id, claimed_capability, supporting_text } = args;
6370
+
6371
+ const safeguard = CIS_SAFEGUARDS[safeguard_id];
6372
+ if (!safeguard) {
6373
+ throw new Error(`Safeguard ${safeguard_id} not found. Available safeguards: ${Object.keys(CIS_SAFEGUARDS).join(', ')}`);
6374
+ }
6375
+
6376
+ const validation = this.validateCapabilityClaim(
6377
+ vendor_name,
6378
+ safeguard,
6379
+ claimed_capability,
6380
+ supporting_text
6381
+ );
6382
+
6383
+ return {
6384
+ content: [
6385
+ {
6386
+ type: 'text',
6387
+ text: JSON.stringify(validation, null, 2),
6388
+ },
6389
+ ],
6390
+ };
6391
+ }
6392
+
6393
+ private validateCapabilityClaim(
6394
+ vendorName: string,
6395
+ safeguard: SafeguardElement,
6396
+ claimedCapability: string,
6397
+ supportingText: string
6398
+ ): ValidationResult {
6399
+ const text = supportingText.toLowerCase();
6400
+
6401
+ // Detect tool type and validate domain match
6402
+ const detectedToolType = this.detectToolType(supportingText);
6403
+ const domainValidation = this.validateDomainMatch(safeguard.id, claimedCapability, detectedToolType);
6404
+
6405
+ // Adjust capability if domain mismatch detected
6406
+ let effectiveCapability = claimedCapability;
6407
+ let originalClaim: string | undefined;
6408
+
6409
+ if (domainValidation.should_adjust_capability) {
6410
+ originalClaim = claimedCapability;
6411
+ effectiveCapability = domainValidation.adjusted_capability!;
6412
+ }
6413
+
6414
+ // Perform actual analysis of the supporting text
6415
+ const actualAnalysis = this.performEnhancedSafeguardAnalysis(vendorName, safeguard, supportingText);
6416
+
6417
+ // Calculate coverage percentages
6418
+ const coreCoverage = this.analyzeBinaryElementCoverage(text, safeguard.coreRequirements);
6419
+ const subElementCoverage = this.analyzeBinaryElementCoverage(text, safeguard.subTaxonomicalElements);
6420
+ const governanceCoverage = this.analyzeBinaryElementCoverage(text, safeguard.governanceElements);
6421
+
6422
+ const corePercentage = safeguard.coreRequirements.length > 0 ?
6423
+ (coreCoverage.coveredElements.length / safeguard.coreRequirements.length) * 100 : 0;
6424
+ const subElementPercentage = safeguard.subTaxonomicalElements.length > 0 ?
6425
+ (subElementCoverage.coveredElements.length / safeguard.subTaxonomicalElements.length) * 100 : 0;
6426
+ const governancePercentage = safeguard.governanceElements.length > 0 ?
6427
+ (governanceCoverage.coveredElements.length / safeguard.governanceElements.length) * 100 : 0;
6428
+
6429
+ // Validate claim against criteria (using effective capability after domain adjustment)
6430
+ const validation = this.assessClaimAlignment(
6431
+ effectiveCapability,
6432
+ actualAnalysis,
6433
+ corePercentage,
6434
+ subElementPercentage,
6435
+ governancePercentage,
6436
+ text
6437
+ );
6438
+
6439
+ // Add domain validation gaps if capability was adjusted
6440
+ if (domainValidation.should_adjust_capability) {
6441
+ validation.gaps.unshift(`Domain mismatch: ${domainValidation.reasoning}`);
6442
+ validation.recommendations.unshift(`Correct capability mapping should be '${effectiveCapability.toUpperCase()}' for ${detectedToolType} tools`);
6443
+ // Reduce confidence for domain mismatches
6444
+ validation.confidence = Math.max(validation.confidence - 20, 0);
6445
+ }
6446
+
6447
+ return {
6448
+ vendor: vendorName,
6449
+ safeguard_id: safeguard.id,
6450
+ safeguard_title: safeguard.title,
6451
+ claimed_capability: claimedCapability,
6452
+ validation_status: validation.status,
6453
+ confidence_score: validation.confidence,
6454
+ evidence_analysis: {
6455
+ core_requirements_coverage: Math.round(corePercentage),
6456
+ sub_elements_coverage: Math.round(subElementPercentage),
6457
+ governance_alignment: Math.round(governancePercentage),
6458
+ language_consistency: validation.languageConsistency
6459
+ },
6460
+ domain_validation: {
6461
+ required_tool_type: domainValidation.required_tool_types.join('/'),
6462
+ detected_tool_type: detectedToolType,
6463
+ domain_match: domainValidation.domain_match,
6464
+ capability_adjusted: domainValidation.should_adjust_capability,
6465
+ original_claim: originalClaim
6466
+ },
6467
+ gaps_identified: validation.gaps,
6468
+ strengths_identified: validation.strengths,
6469
+ recommendations: validation.recommendations,
6470
+ detailed_feedback: validation.feedback
6471
+ };
6472
+ }
6473
+
6474
+ private assessClaimAlignment(
6475
+ claimedCapability: string,
6476
+ actualAnalysis: VendorAnalysis,
6477
+ corePercentage: number,
6478
+ subElementPercentage: number,
6479
+ governancePercentage: number,
6480
+ text: string
6481
+ ): {
6482
+ status: 'SUPPORTED' | 'QUESTIONABLE' | 'UNSUPPORTED';
6483
+ confidence: number;
6484
+ languageConsistency: number;
6485
+ gaps: string[];
6486
+ strengths: string[];
6487
+ recommendations: string[];
6488
+ feedback: string;
6489
+ } {
6490
+ const gaps: string[] = [];
6491
+ const strengths: string[] = [];
6492
+ const recommendations: string[] = [];
6493
+ let languageConsistency = 0;
6494
+ let alignmentScore = 0;
6495
+
6496
+ switch (claimedCapability.toLowerCase()) {
6497
+ case 'full':
6498
+ // Validate FULL claim
6499
+ if (corePercentage >= 70 && subElementPercentage >= 40) {
6500
+ alignmentScore = 85;
6501
+ strengths.push('High coverage of core requirements and sub-elements');
6502
+ } else if (corePercentage >= 80 && subElementPercentage >= 30) {
6503
+ // Alternative path: very high core with moderate sub-elements
6504
+ alignmentScore = 80;
6505
+ strengths.push('Very high core requirements coverage with adequate sub-element coverage');
6506
+ } else {
6507
+ alignmentScore = Math.max(0, (corePercentage + subElementPercentage) / 2 - 15);
6508
+ if (corePercentage < 70) gaps.push(`Core requirements coverage (${Math.round(corePercentage)}%) below FULL threshold (70%)`);
6509
+ if (subElementPercentage < 40) gaps.push(`Sub-element coverage (${Math.round(subElementPercentage)}%) below FULL threshold (40%)`);
6510
+ }
6511
+
6512
+ // Check for conflicting facilitation language
6513
+ if (this.hasFacilitationLanguage(text)) {
6514
+ alignmentScore -= 30;
6515
+ gaps.push('Contains facilitation language inconsistent with FULL implementation claim');
6516
+ }
6517
+
6518
+ languageConsistency = this.assessImplementationLanguage(text);
6519
+ break;
6520
+
6521
+ case 'partial':
6522
+ // Validate PARTIAL claim
6523
+ if (corePercentage >= 30 || (corePercentage > 0 && subElementPercentage >= 20)) {
6524
+ alignmentScore = 75;
6525
+ strengths.push('Appropriate coverage level for PARTIAL implementation');
6526
+ } else {
6527
+ alignmentScore = Math.max(0, corePercentage + subElementPercentage - 10);
6528
+ gaps.push(`Coverage too low even for PARTIAL claim: ${Math.round(corePercentage)}% core, ${Math.round(subElementPercentage)}% sub-elements`);
6529
+ }
6530
+
6531
+ // Check for scope boundary definition
6532
+ if (this.hasScopeBoundaries(text)) {
6533
+ strengths.push('Clearly defines scope boundaries and limitations');
6534
+ alignmentScore += 10;
6535
+ } else {
6536
+ gaps.push('Should clearly define scope boundaries for PARTIAL implementation');
6537
+ recommendations.push('Specify exactly which elements are covered and which are not');
6538
+ }
6539
+
6540
+ languageConsistency = this.assessImplementationLanguage(text);
6541
+ break;
6542
+
6543
+ case 'facilitates':
6544
+ // Validate FACILITATES claim
6545
+ if (this.hasFacilitationLanguage(text) || actualAnalysis.capabilities.facilitates) {
6546
+ alignmentScore = 80;
6547
+ strengths.push('Contains appropriate facilitation and enablement language');
6548
+ } else {
6549
+ alignmentScore = 40;
6550
+ gaps.push('Lacks clear facilitation language (enables, supports, provides framework)');
6551
+ }
6552
+
6553
+ // Check that it doesn't claim direct implementation
6554
+ if (this.hasDirectImplementationLanguage(text)) {
6555
+ // Special handling: If it lacks facilitation language AND claims implementation, stay QUESTIONABLE
6556
+ if (alignmentScore <= 40) {
6557
+ alignmentScore = 45; // Keep it in QUESTIONABLE range
6558
+ } else {
6559
+ alignmentScore -= 15;
6560
+ }
6561
+ gaps.push('Claims direct implementation, inconsistent with FACILITATES capability');
6562
+ }
6563
+
6564
+ languageConsistency = this.assessFacilitationLanguage(text);
6565
+ break;
6566
+
6567
+ case 'governance':
6568
+ // Validate GOVERNANCE claim
6569
+ if (governancePercentage >= 60 || actualAnalysis.capabilities.governance) {
6570
+ alignmentScore = 85;
6571
+ strengths.push('Strong governance element coverage and policy management language');
6572
+ } else {
6573
+ alignmentScore = Math.max(30, governancePercentage);
6574
+ gaps.push(`Governance element coverage (${Math.round(governancePercentage)}%) below expected threshold (60%)`);
6575
+ }
6576
+
6577
+ languageConsistency = this.assessGovernanceLanguage(text);
6578
+ break;
6579
+
6580
+ case 'validates':
6581
+ // Validate VALIDATES claim
6582
+ if (actualAnalysis.capabilities.validates) {
6583
+ alignmentScore = 85;
6584
+ strengths.push('Contains evidence collection and reporting capabilities');
6585
+ } else {
6586
+ alignmentScore = 30;
6587
+ gaps.push('Lacks validation language (audit, report, evidence, verify, monitor)');
6588
+ }
6589
+
6590
+ languageConsistency = this.assessValidationLanguage(text);
6591
+ break;
6592
+
6593
+ default:
6594
+ alignmentScore = 0;
6595
+ gaps.push(`Unknown capability type: ${claimedCapability}`);
6596
+ languageConsistency = 0;
6597
+ }
6598
+
6599
+ // Determine overall status
6600
+ let status: 'SUPPORTED' | 'QUESTIONABLE' | 'UNSUPPORTED';
6601
+ if (alignmentScore >= 70) {
6602
+ status = 'SUPPORTED';
6603
+ } else if (alignmentScore >= 40) {
6604
+ status = 'QUESTIONABLE';
6605
+ } else {
6606
+ status = 'UNSUPPORTED';
6607
+ }
6608
+
6609
+ // Generate recommendations
6610
+ if (gaps.length > 0) {
6611
+ recommendations.push('Address identified gaps to strengthen capability claim');
6612
+ }
6613
+ if (status === 'QUESTIONABLE') {
6614
+ recommendations.push('Provide additional evidence or clarify scope to support claim');
6615
+ }
6616
+
6617
+ const feedback = this.generateValidationFeedback(claimedCapability, status, gaps, strengths, alignmentScore);
6618
+
6619
+ return {
6620
+ status,
6621
+ confidence: Math.round(alignmentScore),
6622
+ languageConsistency: Math.round(languageConsistency),
6623
+ gaps,
6624
+ strengths,
6625
+ recommendations,
6626
+ feedback
6627
+ };
6628
+ }
6629
+
6630
+ private hasFacilitationLanguage(text: string): boolean {
6631
+ const facilitationPatterns = [
6632
+ 'enables', 'facilitates', 'supports', 'helps', 'provides framework',
6633
+ 'creates infrastructure', 'enables organizations', 'supports compliance',
6634
+ 'provides data', 'enriches', 'supplements', 'feeds data'
6635
+ ];
6636
+ return facilitationPatterns.some(pattern => text.includes(pattern));
6637
+ }
6638
+
6639
+ private hasScopeBoundaries(text: string): boolean {
6640
+ const boundaryPatterns = [
6641
+ 'covers', 'but not', 'limited to', 'specifically', 'only', 'excludes',
6642
+ 'scope includes', 'scope excludes', 'within', 'applies to'
6643
+ ];
6644
+ return boundaryPatterns.some(pattern => text.includes(pattern));
6645
+ }
6646
+
6647
+ private hasDirectImplementationLanguage(text: string): boolean {
6648
+ const implementationPatterns = [
6649
+ 'directly implements', 'performs', 'executes', 'scans', 'catalogs',
6650
+ 'inventories', 'manages assets', 'controls access', 'blocks threats'
6651
+ ];
6652
+ return implementationPatterns.some(pattern => text.includes(pattern));
6653
+ }
6654
+
6655
+ private assessImplementationLanguage(text: string): number {
6656
+ const implementationKeywords = [
6657
+ 'implements', 'performs', 'executes', 'manages', 'controls', 'maintains',
6658
+ 'establishes', 'configures', 'monitors', 'tracks', 'inventories'
6659
+ ];
6660
+ return this.calculateKeywordScore(text, implementationKeywords) * 100;
6661
+ }
6662
+
6663
+ private assessFacilitationLanguage(text: string): number {
6664
+ const facilitationKeywords = [
6665
+ 'enables', 'facilitates', 'supports', 'helps', 'enhances', 'improves',
6666
+ 'streamlines', 'automates', 'optimizes', 'provides framework'
6667
+ ];
6668
+ return this.calculateKeywordScore(text, facilitationKeywords) * 100;
6669
+ }
6670
+
6671
+ private assessGovernanceLanguage(text: string): number {
6672
+ const governanceKeywords = [
6673
+ 'policy', 'governance', 'compliance', 'oversight', 'management',
6674
+ 'framework', 'procedures', 'processes', 'controls', 'standards'
6675
+ ];
6676
+ return this.calculateKeywordScore(text, governanceKeywords) * 100;
6677
+ }
6678
+
6679
+ private assessValidationLanguage(text: string): number {
6680
+ const validationKeywords = [
6681
+ 'audit', 'validate', 'verify', 'report', 'evidence', 'monitor',
6682
+ 'assess', 'check', 'review', 'attest', 'compliance', 'compliance tracking',
6683
+ 'compliance reports', 'audit capabilities', 'audit trail', 'reporting capabilities'
6684
+ ];
6685
+ return this.calculateKeywordScore(text, validationKeywords) * 100;
6686
+ }
6687
+
6688
+ private detectToolType(text: string): string {
6689
+ const lowerText = text.toLowerCase();
6690
+
6691
+ // Inventory/Asset Management tools
6692
+ const inventoryKeywords = [
6693
+ 'asset management', 'inventory', 'cmdb', 'discovery', 'asset discovery',
6694
+ 'hardware inventory', 'software inventory', 'device inventory', 'asset tracking',
6695
+ 'configuration management database', 'it asset management', 'endpoint discovery'
6696
+ ];
6697
+
6698
+ // Identity/Authentication tools
6699
+ const identityKeywords = [
6700
+ 'identity management', 'iam', 'active directory', 'ldap', 'sso', 'single sign-on',
6701
+ 'mfa', 'multi-factor', 'authentication', 'identity provider', 'access management',
6702
+ 'user management', 'account management', 'directory service'
6703
+ ];
6704
+
6705
+ // Vulnerability Management tools
6706
+ const vulnerabilityKeywords = [
6707
+ 'vulnerability scanner', 'vulnerability management', 'patch management',
6708
+ 'security scanner', 'vuln scan', 'penetration test', 'security assessment',
6709
+ 'scanning capabilities', 'vulnerability scanning', 'network discovery'
6710
+ ];
6711
+
6712
+ // Network Security tools
6713
+ const networkSecurityKeywords = [
6714
+ 'firewall', 'network access control', 'nac', 'network security', 'intrusion detection',
6715
+ 'network monitoring', 'traffic analysis', 'network segmentation'
6716
+ ];
6717
+
6718
+ // Threat Intelligence/Data Enrichment tools
6719
+ const threatIntelKeywords = [
6720
+ 'threat intelligence', 'threat intel', 'threat feed', 'security intelligence',
6721
+ 'enrichment', 'data feed', 'contextual data', 'risk intelligence',
6722
+ 'cyber threat intelligence', 'ioc feed', 'threat data'
6723
+ ];
6724
+
6725
+ // GRC/Governance tools
6726
+ const governanceKeywords = [
6727
+ 'grc', 'governance', 'compliance management', 'policy management',
6728
+ 'risk management', 'audit management', 'compliance platform'
6729
+ ];
6730
+
6731
+ // Security Analytics/SIEM tools
6732
+ const analyticsKeywords = [
6733
+ 'siem', 'security analytics', 'log management', 'security monitoring',
6734
+ 'event correlation', 'security orchestration', 'soar'
6735
+ ];
6736
+
6737
+ // Check for tool type patterns - order by specificity (most specific first)
6738
+ if (threatIntelKeywords.some(keyword => lowerText.includes(keyword))) {
6739
+ return 'threat_intelligence';
6740
+ } else if (vulnerabilityKeywords.some(keyword => lowerText.includes(keyword))) {
6741
+ return 'vulnerability_management';
6742
+ } else if (identityKeywords.some(keyword => lowerText.includes(keyword))) {
6743
+ return 'identity_management';
6744
+ } else if (networkSecurityKeywords.some(keyword => lowerText.includes(keyword))) {
6745
+ return 'network_security';
6746
+ } else if (governanceKeywords.some(keyword => lowerText.includes(keyword))) {
6747
+ return 'governance';
6748
+ } else if (analyticsKeywords.some(keyword => lowerText.includes(keyword))) {
6749
+ return 'security_analytics';
6750
+ } else if (inventoryKeywords.some(keyword => lowerText.includes(keyword))) {
6751
+ return 'inventory';
6752
+ }
6753
+
6754
+ return 'unknown';
6755
+ }
6756
+
6757
+ private validateDomainMatch(
6758
+ safeguardId: string,
6759
+ claimedCapability: string,
6760
+ detectedToolType: string
6761
+ ): {
6762
+ domain_match: boolean;
6763
+ required_tool_types: string[];
6764
+ should_adjust_capability: boolean;
6765
+ adjusted_capability?: string;
6766
+ reasoning: string;
6767
+ } {
6768
+ const domainReq = SAFEGUARD_DOMAIN_REQUIREMENTS[safeguardId];
6769
+
6770
+ if (!domainReq) {
6771
+ return {
6772
+ domain_match: true,
6773
+ required_tool_types: [],
6774
+ should_adjust_capability: false,
6775
+ reasoning: 'No domain restrictions defined for this safeguard'
6776
+ };
6777
+ }
6778
+
6779
+ const isFullOrPartial = ['full', 'partial'].includes(claimedCapability.toLowerCase());
6780
+ const toolTypeMatches = domainReq.required_tool_types.includes(detectedToolType);
6781
+
6782
+ if (isFullOrPartial && !toolTypeMatches) {
6783
+ return {
6784
+ domain_match: false,
6785
+ required_tool_types: domainReq.required_tool_types,
6786
+ should_adjust_capability: true,
6787
+ adjusted_capability: 'facilitates',
6788
+ reasoning: `${domainReq.domain} safeguard requires ${domainReq.required_tool_types.join('/')} tool types for FULL/PARTIAL coverage. Detected tool type '${detectedToolType}' can only facilitate implementation.`
6789
+ };
6790
+ }
6791
+
6792
+ return {
6793
+ domain_match: true,
6794
+ required_tool_types: domainReq.required_tool_types,
6795
+ should_adjust_capability: false,
6796
+ reasoning: toolTypeMatches ?
6797
+ `Tool type '${detectedToolType}' is appropriate for ${domainReq.domain} safeguard` :
6798
+ 'No domain validation required for this capability type'
6799
+ };
6800
+ }
6801
+
6802
+ private generateValidationFeedback(
6803
+ claimedCapability: string,
6804
+ status: string,
6805
+ gaps: string[],
6806
+ strengths: string[],
6807
+ score: number
6808
+ ): string {
6809
+ let feedback = `Validation of ${claimedCapability.toUpperCase()} capability claim: ${status} (${Math.round(score)}% alignment)\n\n`;
6810
+
6811
+ if (strengths.length > 0) {
6812
+ feedback += `STRENGTHS:\n${strengths.map(s => `• ${s}`).join('\n')}\n\n`;
6813
+ }
6814
+
6815
+ if (gaps.length > 0) {
6816
+ feedback += `GAPS IDENTIFIED:\n${gaps.map(g => `• ${g}`).join('\n')}\n\n`;
6817
+ }
6818
+
6819
+ feedback += `ASSESSMENT: `;
6820
+ switch (status) {
6821
+ case 'SUPPORTED':
6822
+ feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability.';
6823
+ break;
6824
+ case 'QUESTIONABLE':
6825
+ feedback += 'The vendor\'s evidence partially supports their claim but has notable gaps or inconsistencies.';
6826
+ break;
6827
+ case 'UNSUPPORTED':
6828
+ feedback += 'The vendor\'s evidence does not adequately support their claimed capability.';
6829
+ break;
6830
+ }
6831
+
6832
+ return feedback;
6833
+ }
6834
+
6265
6835
  async run() {
6266
6836
  const transport = new StdioServerTransport();
6267
6837
  await this.server.connect(transport);