framework-mcp 1.1.2 → 1.1.3

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/src/index.ts CHANGED
@@ -30,30 +30,22 @@ interface VendorAnalysis {
30
30
  vendor: string;
31
31
  safeguardId: string;
32
32
  safeguardTitle: string;
33
- // Primary capability categorization
34
- capability: 'full' | 'partial' | 'facilitates' | 'governance' | 'validates' | 'none';
35
- // Detailed breakdown for complex products
33
+ // Primary capability categorization - what role does this tool play?
34
+ capability: 'full' | 'partial' | 'facilitates' | 'governance' | 'validates';
35
+ // Detailed capability breakdown
36
36
  capabilities: {
37
- full: boolean; // Does the safeguard completely (all core + sub-taxonomical elements)
38
- partial: boolean; // Does some of the safeguard elements
39
- facilitates: boolean; // Helps with data or automation for the safeguard
40
- governance: boolean; // Controls policy, process, procedures
41
- validates: boolean; // Provides evidence of safeguard implementation
37
+ full: boolean; // Directly implements the core safeguard functionality
38
+ partial: boolean; // Implements limited aspects of the safeguard
39
+ facilitates: boolean; // Enhances or enables safeguard implementation by others
40
+ governance: boolean; // Provides policy, process, and oversight capabilities
41
+ validates: boolean; // Provides evidence, audit, and validation reporting
42
42
  };
43
43
  confidence: number;
44
44
  reasoning: string;
45
45
  evidence: string[];
46
- // Coverage analysis (binary: met or not met)
47
- elementsCovered: {
48
- coreRequirements: string[]; // Green elements addressed
49
- subTaxonomicalElements: string[]; // Yellow elements addressed
50
- governanceElements: string[]; // Orange elements addressed
51
- implementationMethods: string[]; // Gray elements used
52
- };
53
- elementsNotCovered: {
54
- coreRequirements: string[];
55
- subTaxonomicalElements: string[];
56
- };
46
+ // Capability-focused descriptions (replaces element coverage scoring)
47
+ toolCapabilityDescription: string; // What type of tool this is and its role
48
+ recommendedUse: string; // How practitioners should use this tool
57
49
  }
58
50
 
59
51
  interface AnalysisResult {
@@ -91,12 +83,10 @@ interface ValidationResult {
91
83
  claimed_capability: string;
92
84
  validation_status: 'SUPPORTED' | 'QUESTIONABLE' | 'UNSUPPORTED';
93
85
  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
- };
86
+ actual_capability_detected: string; // What capability the tool actually provides
87
+ capability_confidence: number; // Confidence in the detected capability
88
+ tool_capability_description: string; // Description of what type of tool this is
89
+ recommended_use: string; // How practitioners should use this tool
100
90
  domain_validation: {
101
91
  required_tool_type: string;
102
92
  detected_tool_type: string;
@@ -119,27 +109,27 @@ const SAFEGUARD_DOMAIN_REQUIREMENTS: Record<string, {
119
109
  "1.1": {
120
110
  domain: "Asset Inventory",
121
111
  required_tool_types: ["inventory", "asset_management", "cmdb", "discovery"],
122
- description: "Only asset inventory and discovery tools can provide FULL/PARTIAL coverage"
112
+ description: "Only asset inventory and discovery tools can provide FULL/PARTIAL implementation capability"
123
113
  },
124
114
  "1.2": {
125
115
  domain: "Asset Management",
126
116
  required_tool_types: ["inventory", "asset_management", "network_security", "nac"],
127
- description: "Asset management or network access control tools required for FULL/PARTIAL"
117
+ description: "Asset management or network access control tools required for FULL/PARTIAL implementation capability"
128
118
  },
129
119
  "5.1": {
130
120
  domain: "Account Management",
131
121
  required_tool_types: ["identity_management", "iam", "directory", "account_management"],
132
- description: "Identity and account management tools required for FULL/PARTIAL"
122
+ description: "Identity and account management tools required for FULL/PARTIAL implementation capability"
133
123
  },
134
124
  "6.3": {
135
125
  domain: "Authentication",
136
126
  required_tool_types: ["mfa", "authentication", "identity_management", "iam"],
137
- description: "Multi-factor authentication and identity tools required for FULL/PARTIAL"
127
+ description: "Multi-factor authentication and identity tools required for FULL/PARTIAL implementation capability"
138
128
  },
139
129
  "7.1": {
140
130
  domain: "Vulnerability Management",
141
131
  required_tool_types: ["vulnerability_management", "vulnerability_scanner", "patch_management"],
142
- description: "Vulnerability management and scanning tools required for FULL/PARTIAL"
132
+ description: "Vulnerability management and scanning tools required for FULL/PARTIAL implementation capability"
143
133
  }
144
134
  };
145
135
 
@@ -5600,7 +5590,7 @@ export class GRCAnalysisServer {
5600
5590
  tools: [
5601
5591
  {
5602
5592
  name: 'analyze_vendor_response',
5603
- description: 'Analyze a vendor response for a specific CIS Control safeguard against the 4 GRC attributes with detailed sub-element coverage',
5593
+ description: 'Analyze a vendor response to determine their tool capability role (Full Implementation, Partial Implementation, Facilitates, Governance, or Validates) for a specific CIS Control safeguard',
5604
5594
  inputSchema: {
5605
5595
  type: 'object',
5606
5596
  properties: {
@@ -5615,7 +5605,7 @@ export class GRCAnalysisServer {
5615
5605
  },
5616
5606
  response_text: {
5617
5607
  type: 'string',
5618
- description: 'Vendor response text to analyze'
5608
+ description: 'Vendor response text describing their tool capabilities for the safeguard'
5619
5609
  }
5620
5610
  },
5621
5611
  required: ['vendor_name', 'safeguard_id', 'response_text']
@@ -5643,7 +5633,7 @@ export class GRCAnalysisServer {
5643
5633
  } as Tool,
5644
5634
  {
5645
5635
  name: 'validate_coverage_claim',
5646
- description: 'Validate a vendor\'s coverage claim (FULL/PARTIAL) against specific safeguard requirements',
5636
+ description: 'Validate a vendor\'s implementation capability claim (FULL/PARTIAL) against specific safeguard requirements and evidence quality',
5647
5637
  inputSchema: {
5648
5638
  type: 'object',
5649
5639
  properties: {
@@ -5659,16 +5649,16 @@ export class GRCAnalysisServer {
5659
5649
  coverage_claim: {
5660
5650
  type: 'string',
5661
5651
  enum: ['FULL', 'PARTIAL'],
5662
- description: 'Vendor\'s coverage claim'
5652
+ description: 'Vendor\'s implementation capability claim (FULL = complete implementation, PARTIAL = limited scope implementation)'
5663
5653
  },
5664
5654
  response_text: {
5665
5655
  type: 'string',
5666
- description: 'Vendor response explaining their coverage'
5656
+ description: 'Vendor response explaining their implementation capabilities'
5667
5657
  },
5668
5658
  capabilities: {
5669
5659
  type: 'array',
5670
5660
  items: { type: 'string' },
5671
- description: 'List of vendor capabilities/attributes (Governance, Facilitates, Validates)'
5661
+ description: 'List of additional vendor capability types (Governance, Facilitates, Validates)'
5672
5662
  }
5673
5663
  },
5674
5664
  required: ['vendor_name', 'safeguard_id', 'coverage_claim', 'response_text', 'capabilities']
@@ -5695,7 +5685,7 @@ export class GRCAnalysisServer {
5695
5685
  } as Tool,
5696
5686
  {
5697
5687
  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',
5688
+ description: 'Validate whether a vendor\'s claimed capability role (Full Implementation/Partial Implementation/Facilitates/Governance/Validates) is actually supported by their supporting evidence for a specific CIS safeguard',
5699
5689
  inputSchema: {
5700
5690
  type: 'object',
5701
5691
  properties: {
@@ -5712,11 +5702,11 @@ export class GRCAnalysisServer {
5712
5702
  claimed_capability: {
5713
5703
  type: 'string',
5714
5704
  enum: ['full', 'partial', 'facilitates', 'governance', 'validates'],
5715
- description: 'Vendor\'s claimed capability mapping for this safeguard'
5705
+ description: 'Vendor\'s claimed capability role: full (complete implementation), partial (limited implementation), facilitates (enables/enhances), governance (policies/processes), validates (evidence/reporting)'
5716
5706
  },
5717
5707
  supporting_text: {
5718
5708
  type: 'string',
5719
- description: 'Vendor\'s supporting text blob explaining how they meet the claimed capability'
5709
+ description: 'Vendor\'s supporting evidence explaining how their tool fulfills the claimed capability role'
5720
5710
  }
5721
5711
  },
5722
5712
  required: ['safeguard_id', 'claimed_capability', 'supporting_text']
@@ -5727,28 +5717,49 @@ export class GRCAnalysisServer {
5727
5717
 
5728
5718
  this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
5729
5719
  const { name, arguments: args } = request.params;
5720
+ const startTime = Date.now();
5730
5721
 
5731
5722
  try {
5723
+ let result;
5732
5724
  switch (name) {
5733
5725
  case 'analyze_vendor_response':
5734
- return await this.analyzeVendorResponse(args);
5726
+ result = await this.analyzeVendorResponse(args);
5727
+ break;
5735
5728
  case 'get_safeguard_details':
5736
- return await this.getSafeguardDetails(args);
5729
+ result = await this.getSafeguardDetails(args);
5730
+ break;
5737
5731
  case 'validate_coverage_claim':
5738
- return await this.validateCoverageClaim(args);
5732
+ result = await this.validateCoverageClaim(args);
5733
+ break;
5739
5734
  case 'list_available_safeguards':
5740
- return await this.listAvailableSafeguards(args);
5735
+ result = await this.listAvailableSafeguards(args);
5736
+ break;
5741
5737
  case 'validate_vendor_mapping':
5742
- return await this.validateVendorMapping(args);
5738
+ result = await this.validateVendorMapping(args);
5739
+ break;
5743
5740
  default:
5744
5741
  throw new Error(`Unknown tool: ${name}`);
5745
5742
  }
5743
+
5744
+ // Record successful execution time
5745
+ const executionTime = Date.now() - startTime;
5746
+ this.recordToolExecution(name, executionTime);
5747
+
5748
+ return result;
5746
5749
  } catch (error) {
5750
+ // Record error and performance metrics
5751
+ this.performanceMetrics.errorCount++;
5752
+ const executionTime = Date.now() - startTime;
5753
+ this.recordToolExecution(`${name}_error`, executionTime);
5754
+
5755
+ const errorMessage = this.formatErrorMessage(error, name);
5756
+ console.error(`[FrameworkMCP] Tool execution error: ${name}`, error);
5757
+
5747
5758
  return {
5748
5759
  content: [
5749
5760
  {
5750
5761
  type: 'text',
5751
- text: `Error: ${error instanceof Error ? error.message : String(error)}`,
5762
+ text: errorMessage,
5752
5763
  },
5753
5764
  ],
5754
5765
  };
@@ -5759,10 +5770,16 @@ export class GRCAnalysisServer {
5759
5770
  private async getSafeguardDetails(args: any) {
5760
5771
  const { safeguard_id, include_examples = true } = args;
5761
5772
 
5762
- const safeguard = CIS_SAFEGUARDS[safeguard_id];
5763
- if (!safeguard) {
5764
- throw new Error(`Safeguard ${safeguard_id} not found. Use list_available_safeguards to see available safeguards.`);
5773
+ // Input validation
5774
+ this.validateSafeguardId(safeguard_id);
5775
+
5776
+ // Check cache first
5777
+ const cached = this.getCachedSafeguardDetails(safeguard_id, include_examples);
5778
+ if (cached) {
5779
+ return cached;
5765
5780
  }
5781
+
5782
+ const safeguard = CIS_SAFEGUARDS[safeguard_id];
5766
5783
 
5767
5784
  const result = {
5768
5785
  ...safeguard,
@@ -5792,7 +5809,7 @@ export class GRCAnalysisServer {
5792
5809
  }
5793
5810
  };
5794
5811
 
5795
- return {
5812
+ const response = {
5796
5813
  content: [
5797
5814
  {
5798
5815
  type: 'text',
@@ -5800,11 +5817,24 @@ export class GRCAnalysisServer {
5800
5817
  },
5801
5818
  ],
5802
5819
  };
5820
+
5821
+ // Cache the result for future requests
5822
+ this.setCachedSafeguardDetails(safeguard_id, include_examples, response);
5823
+
5824
+ return response;
5803
5825
  }
5804
5826
 
5805
5827
  private async listAvailableSafeguards(args: any) {
5806
5828
  const { implementation_group, security_function } = args;
5807
5829
 
5830
+ // Check cache for complete safeguard list (only if no filters applied)
5831
+ if (!implementation_group && !security_function && this.cache.safeguardList) {
5832
+ const cacheAge = Date.now() - this.cache.safeguardList.timestamp;
5833
+ if (cacheAge < 10 * 60 * 1000) { // 10 minute cache for safeguard list
5834
+ return this.cache.safeguardList.data;
5835
+ }
5836
+ }
5837
+
5808
5838
  let safeguards = Object.values(CIS_SAFEGUARDS);
5809
5839
 
5810
5840
  if (implementation_group) {
@@ -5831,7 +5861,7 @@ export class GRCAnalysisServer {
5831
5861
  }))
5832
5862
  };
5833
5863
 
5834
- return {
5864
+ const response = {
5835
5865
  content: [
5836
5866
  {
5837
5867
  type: 'text',
@@ -5839,17 +5869,32 @@ export class GRCAnalysisServer {
5839
5869
  },
5840
5870
  ],
5841
5871
  };
5872
+
5873
+ // Cache the complete list if no filters were applied
5874
+ if (!implementation_group && !security_function) {
5875
+ this.cache.safeguardList = {
5876
+ data: response,
5877
+ timestamp: Date.now()
5878
+ };
5879
+ }
5880
+
5881
+ return response;
5842
5882
  }
5843
5883
 
5844
5884
  private async analyzeVendorResponse(args: any) {
5845
5885
  const { vendor_name, safeguard_id, response_text } = args;
5846
5886
 
5847
- const safeguard = CIS_SAFEGUARDS[safeguard_id];
5848
- if (!safeguard) {
5849
- throw new Error(`Safeguard ${safeguard_id} not found. Available safeguards: ${Object.keys(CIS_SAFEGUARDS).join(', ')}`);
5887
+ // Input validation
5888
+ this.validateSafeguardId(safeguard_id);
5889
+ this.validateTextInput(response_text, 'Response text');
5890
+
5891
+ if (!vendor_name || typeof vendor_name !== 'string' || vendor_name.trim().length === 0) {
5892
+ throw new Error('Vendor name is required');
5850
5893
  }
5851
5894
 
5852
- const analysis = this.performEnhancedSafeguardAnalysis(vendor_name, safeguard, response_text);
5895
+ const safeguard = CIS_SAFEGUARDS[safeguard_id];
5896
+
5897
+ const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
5853
5898
 
5854
5899
  return {
5855
5900
  content: [
@@ -5869,7 +5914,7 @@ export class GRCAnalysisServer {
5869
5914
  throw new Error(`Safeguard ${safeguard_id} not found`);
5870
5915
  }
5871
5916
 
5872
- const analysis = this.performEnhancedSafeguardAnalysis(vendor_name, safeguard, response_text);
5917
+ const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
5873
5918
 
5874
5919
  // Validate the coverage claim
5875
5920
  const validation = this.validateClaim(coverage_claim, analysis, capabilities, safeguard);
@@ -5891,182 +5936,284 @@ export class GRCAnalysisServer {
5891
5936
  };
5892
5937
  }
5893
5938
 
5894
- private performEnhancedSafeguardAnalysis(vendorName: string, safeguard: SafeguardElement, responseText: string): VendorAnalysis {
5939
+ private performCapabilityAnalysis(vendorName: string, safeguard: SafeguardElement, responseText: string): VendorAnalysis {
5895
5940
  const text = responseText.toLowerCase();
5896
5941
 
5897
- // Capability detection keywords
5898
- const governanceKeywords = [
5942
+ // Step 1: Determine what type of capability this tool is claiming
5943
+ const claimedCapability = this.determineClaimedCapability(text, safeguard);
5944
+
5945
+ // Step 2: Assess how well the tool executes that specific capability type
5946
+ const qualityAssessment = this.assessCapabilityQuality(text, safeguard, claimedCapability);
5947
+
5948
+ // Step 3: Generate capability-focused analysis
5949
+ return this.generateCapabilityAnalysis(vendorName, safeguard, responseText, claimedCapability, qualityAssessment);
5950
+ }
5951
+
5952
+ private determineClaimedCapability(text: string, safeguard: SafeguardElement): 'full' | 'partial' | 'facilitates' | 'governance' | 'validates' {
5953
+ // Capability detection keywords - focused on what the tool DOES, not what elements it covers
5954
+ const governanceIndicators = [
5899
5955
  'policy', 'policies', 'manage', 'process', 'workflow', 'governance', 'grc',
5900
5956
  'compliance management', 'documented', 'establish', 'maintain', 'procedure',
5901
5957
  'control', 'controls', 'framework', 'standard', 'enterprise risk management',
5902
5958
  'centralized management', 'oversight'
5903
5959
  ];
5904
5960
 
5905
- const facilitatesKeywords = [
5906
- // Technical facilitation (original keywords)
5961
+ const facilitatesIndicators = [
5907
5962
  'improve', 'enhance', 'optimize', 'faster', 'better', 'stronger', 'automate',
5908
5963
  'streamline', 'efficiency', 'facilitate', 'support', 'enable', 'accelerate',
5909
5964
  'api', 'integration', 'data', 'export', 'import', 'sync', 'feed',
5910
- // Data provision and enrichment
5911
5965
  'provides data', 'data source', 'data feeds', 'enrichment', 'data enrichment',
5912
5966
  'supplemental data', 'additional data', 'contextual data', 'threat data',
5913
5967
  'intelligence feeds', 'data aggregation', 'data collection', 'data gathering',
5914
5968
  'feeds data', 'populates', 'informs', 'enriches', 'supplements',
5915
- // Governance/process facilitation (new keywords for tools like Upolicy)
5916
5969
  'enables compliance', 'facilitates implementation', 'supports compliance',
5917
5970
  'creates framework', 'enables organizations', 'infrastructure', 'foundation',
5918
- 'compliance infrastructure', 'audit infrastructure', 'policy framework',
5919
- 'enables effective', 'working together', 'comprehensive coverage',
5920
5971
  'template', 'templates', 'workflow automation', 'orchestration'
5921
5972
  ];
5922
5973
 
5923
- const validatesKeywords = [
5974
+ const validatesIndicators = [
5924
5975
  'audit', 'report', 'evidence', 'verify', 'validate', 'check', 'monitor',
5925
5976
  'compliance', 'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest',
5926
5977
  'dashboard', 'metrics', 'analytics', 'visibility', 'alert', 'attestation',
5927
5978
  'compliance tracking', 'audit trail', 'reporting capabilities', 'audit capabilities'
5928
5979
  ];
5929
5980
 
5930
- // Analyze element coverage (binary: covered or not)
5931
- const coreCoverage = this.analyzeBinaryElementCoverage(text, safeguard.coreRequirements);
5932
- const subElementCoverage = this.analyzeBinaryElementCoverage(text, safeguard.subTaxonomicalElements);
5933
- const governanceCoverage = this.analyzeBinaryElementCoverage(text, safeguard.governanceElements);
5934
- const implementationCoverage = this.analyzeBinaryElementCoverage(text, safeguard.implementationSuggestions);
5981
+ // Direct implementation indicators (tools that actually perform the safeguard)
5982
+ const implementationIndicators = this.getImplementationIndicators(safeguard.id);
5983
+
5984
+ // Calculate keyword presence scores
5985
+ const governanceScore = this.calculateKeywordScore(text, governanceIndicators);
5986
+ const facilitatesScore = this.calculateKeywordScore(text, facilitatesIndicators);
5987
+ const validatesScore = this.calculateKeywordScore(text, validatesIndicators);
5988
+ const implementationScore = this.calculateKeywordScore(text, implementationIndicators);
5989
+
5990
+ // Determine claimed capability based on strongest indicators and patterns
5991
+ if (implementationScore > 0.2 && implementationScore >= Math.max(facilitatesScore, governanceScore, validatesScore)) {
5992
+ // Tool claims to directly implement the safeguard
5993
+ return implementationScore > 0.5 ? 'full' : 'partial';
5994
+ } else if (governanceScore > 0.2 && governanceScore >= Math.max(facilitatesScore, validatesScore)) {
5995
+ return 'governance';
5996
+ } else if (validatesScore > 0.2 && validatesScore >= facilitatesScore) {
5997
+ return 'validates';
5998
+ } else {
5999
+ return 'facilitates';
6000
+ }
6001
+ }
5935
6002
 
5936
- // Enhanced capability detection with better scoring
5937
- const governanceScore = this.calculateKeywordScore(text, governanceKeywords);
5938
- const facilitatesScore = this.calculateKeywordScore(text, facilitatesKeywords);
5939
- const validatesScore = this.calculateKeywordScore(text, validatesKeywords);
6003
+ private getImplementationIndicators(safeguardId: string): string[] {
6004
+ // Return specific indicators for what constitutes direct implementation for each safeguard
6005
+ const implementationMap: Record<string, string[]> = {
6006
+ "1.1": ['inventory', 'discovery', 'asset management', 'catalog', 'enumerate', 'scan devices', 'device database'],
6007
+ "1.2": ['unauthorized', 'rogue', 'detect', 'identify unauthorized', 'quarantine', 'block unauthorized'],
6008
+ "5.1": ['account inventory', 'user management', 'identity management', 'account lifecycle', 'user provisioning'],
6009
+ "6.3": ['multi-factor', 'mfa', '2fa', 'authentication', 'two-factor', 'multi-factor authentication'],
6010
+ "7.1": ['vulnerability', 'vuln', 'scanning', 'vulnerability management', 'security testing', 'penetration testing']
6011
+ };
5940
6012
 
5941
- const governanceCapability = governanceScore > 0.3;
5942
- const facilitatesCapability = facilitatesScore > 0.3;
5943
- const validatesCapability = validatesScore > 0.3;
6013
+ return implementationMap[safeguardId] || [];
6014
+ }
6015
+
6016
+ private assessCapabilityQuality(text: string, safeguard: SafeguardElement, claimedCapability: string): {
6017
+ quality: 'excellent' | 'good' | 'fair' | 'poor',
6018
+ confidence: number,
6019
+ evidence: string[],
6020
+ gaps: string[]
6021
+ } {
6022
+ // Assess how well the tool executes the claimed capability type
6023
+ const evidence: string[] = [];
6024
+ const gaps: string[] = [];
5944
6025
 
5945
- // Check for specific facilitation patterns (tools that enable/support compliance)
5946
- const facilitationPatterns = [
5947
- 'enables compliance', 'facilitates implementation', 'creates framework',
5948
- 'policy framework', 'compliance infrastructure', 'audit infrastructure',
5949
- 'enables organizations', 'enables effective', 'working together',
5950
- 'creates the policy framework', 'enables organizations to implement',
5951
- 'facilitates implementation of', 'compliance infrastructure facilitates'
5952
- ];
5953
- const hasFacilitationPattern = facilitationPatterns.some(pattern => text.includes(pattern));
6026
+ // Quality assessment based on capability type
6027
+ let qualityScore = 0;
5954
6028
 
5955
- // Check for explicit non-implementation language
5956
- const nonImplementationPatterns = [
5957
- 'don\'t scan', 'don\'t catalog', 'doesn\'t scan', 'doesn\'t catalog',
5958
- 'not scan', 'not catalog', 'even though we don\'t', 'we don\'t directly',
5959
- 'rather than direct', 'instead of direct'
5960
- ];
5961
- const hasNonImplementationLanguage = nonImplementationPatterns.some(pattern => text.includes(pattern));
6029
+ switch (claimedCapability) {
6030
+ case 'full':
6031
+ case 'partial':
6032
+ qualityScore = this.assessImplementationQuality(text, safeguard, evidence, gaps);
6033
+ break;
6034
+ case 'governance':
6035
+ qualityScore = this.assessGovernanceQuality(text, safeguard, evidence, gaps);
6036
+ break;
6037
+ case 'facilitates':
6038
+ qualityScore = this.assessFacilitationQuality(text, safeguard, evidence, gaps);
6039
+ break;
6040
+ case 'validates':
6041
+ qualityScore = this.assessValidationQuality(text, safeguard, evidence, gaps);
6042
+ break;
6043
+ }
5962
6044
 
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
6045
+ // Convert score to quality rating
6046
+ let quality: 'excellent' | 'good' | 'fair' | 'poor';
6047
+ if (qualityScore >= 0.8) quality = 'excellent';
6048
+ else if (qualityScore >= 0.6) quality = 'good';
6049
+ else if (qualityScore >= 0.4) quality = 'fair';
6050
+ else quality = 'poor';
6051
+
6052
+ return {
6053
+ quality,
6054
+ confidence: Math.round(qualityScore * 100),
6055
+ evidence: evidence.slice(0, 5), // Top 5 pieces of evidence
6056
+ gaps: gaps.slice(0, 3) // Top 3 gaps identified
6057
+ };
6058
+ }
6059
+
6060
+ private assessImplementationQuality(text: string, safeguard: SafeguardElement, evidence: string[], gaps: string[]): number {
6061
+ // Assess quality of direct implementation capability
6062
+ const implementationIndicators = this.getImplementationIndicators(safeguard.id);
6063
+ let score = 0;
5966
6064
 
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;
6065
+ // Check for strong implementation language
6066
+ const strongIndicators = implementationIndicators.filter(indicator => text.includes(indicator.toLowerCase()));
6067
+ if (strongIndicators.length > 0) {
6068
+ score += 0.4;
6069
+ evidence.push(`Strong implementation indicators: ${strongIndicators.join(', ')}`);
6070
+ }
5971
6071
 
5972
- let fullCapability = false;
5973
- let partialCapability = false;
6072
+ // Check for comprehensive functionality description
6073
+ if (text.includes('comprehensive') || text.includes('complete') || text.includes('full')) {
6074
+ score += 0.2;
6075
+ evidence.push('Claims comprehensive functionality');
6076
+ }
5974
6077
 
5975
- // Full capability: High coverage of core requirements + reasonable sub-element coverage
5976
- if (corePercentage >= 70 && subElementPercentage >= 50) {
5977
- fullCapability = true;
6078
+ // Check for automated vs manual implementation
6079
+ if (text.includes('automat') || text.includes('real-time') || text.includes('continuous')) {
6080
+ score += 0.2;
6081
+ evidence.push('Automated implementation capability');
5978
6082
  }
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;
6083
+
6084
+ // Identify potential gaps
6085
+ if (strongIndicators.length === 0) {
6086
+ gaps.push('No clear implementation indicators found');
5982
6087
  }
6088
+
6089
+ return Math.min(score, 1.0);
6090
+ }
5983
6091
 
5984
- // Enhanced primary capability logic
5985
- let primaryCapability: 'full' | 'partial' | 'facilitates' | 'governance' | 'validates' | 'none' = 'none';
6092
+ private assessGovernanceQuality(text: string, safeguard: SafeguardElement, evidence: string[], gaps: string[]): number {
6093
+ const governanceIndicators = ['policy', 'process', 'governance', 'compliance', 'documentation', 'oversight'];
6094
+ let score = 0;
6095
+
6096
+ const foundIndicators = governanceIndicators.filter(indicator => text.includes(indicator));
6097
+ if (foundIndicators.length >= 3) {
6098
+ score += 0.5;
6099
+ evidence.push(`Strong governance capability: ${foundIndicators.join(', ')}`);
6100
+ }
5986
6101
 
5987
- if (fullCapability) {
5988
- primaryCapability = 'full';
5989
- } else if (hasFacilitationPattern || hasNonImplementationLanguage ||
5990
- (facilitatesScore > 0.4 && facilitatesScore > governanceScore * 1.2)) {
5991
- // Prioritize facilitation when:
5992
- // 1. Clear facilitation language patterns detected, OR
5993
- // 2. Explicit non-implementation language (tool doesn't directly implement), OR
5994
- // 3. Facilitates score is substantial AND significantly higher than governance
5995
- primaryCapability = 'facilitates';
5996
- } else if (partialCapability) {
5997
- primaryCapability = 'partial';
5998
- } else if (governanceCapability && (facilitatesCapability || validatesCapability)) {
5999
- // Tools that primarily manage governance but also facilitate/validate
6000
- primaryCapability = 'governance';
6001
- } else if (governanceScore > facilitatesScore && governanceCapability) {
6002
- // Pure governance tools
6003
- primaryCapability = 'governance';
6004
- } else if (validatesScore > facilitatesScore && validatesCapability) {
6005
- // Validation-focused tools
6006
- primaryCapability = 'validates';
6007
- } else if (facilitatesCapability) {
6008
- // Default facilitation
6009
- primaryCapability = 'facilitates';
6102
+ if (text.includes('documented') && text.includes('process')) {
6103
+ score += 0.3;
6104
+ evidence.push('Documented process management');
6010
6105
  }
6106
+
6107
+ return Math.min(score, 1.0);
6108
+ }
6011
6109
 
6012
- // Extract evidence
6013
- const evidence = this.extractEnhancedEvidence(responseText, safeguard);
6110
+ private assessFacilitationQuality(text: string, safeguard: SafeguardElement, evidence: string[], gaps: string[]): number {
6111
+ const facilitationIndicators = ['enhance', 'enable', 'support', 'facilitate', 'improve', 'optimize'];
6112
+ let score = 0;
6113
+
6114
+ const foundIndicators = facilitationIndicators.filter(indicator => text.includes(indicator));
6115
+ if (foundIndicators.length >= 2) {
6116
+ score += 0.4;
6117
+ evidence.push(`Clear facilitation capability: ${foundIndicators.join(', ')}`);
6118
+ }
6119
+
6120
+ return Math.min(score, 1.0);
6121
+ }
6014
6122
 
6015
- // Calculate confidence based on evidence strength and keyword matches
6016
- const keywordConfidence = (governanceScore + facilitatesScore + validatesScore) / 3;
6123
+ private assessValidationQuality(text: string, safeguard: SafeguardElement, evidence: string[], gaps: string[]): number {
6124
+ const validationIndicators = ['audit', 'report', 'monitor', 'track', 'verify', 'validate'];
6125
+ let score = 0;
6017
6126
 
6018
- const totalCoreAndSubElements = safeguard.coreRequirements.length + safeguard.subTaxonomicalElements.length;
6019
- const coveredCoreAndSubElements = coreCoverage.coveredElements.length + subElementCoverage.coveredElements.length;
6020
- const coverageConfidence = totalCoreAndSubElements > 0 ?
6021
- coveredCoreAndSubElements / totalCoreAndSubElements : 0;
6127
+ const foundIndicators = validationIndicators.filter(indicator => text.includes(indicator));
6128
+ if (foundIndicators.length >= 2) {
6129
+ score += 0.4;
6130
+ evidence.push(`Strong validation capability: ${foundIndicators.join(', ')}`);
6131
+ }
6022
6132
 
6023
- const confidence = Math.min(
6024
- (keywordConfidence * 0.4 + coverageConfidence * 0.6) * 100,
6025
- 100
6026
- );
6133
+ return Math.min(score, 1.0);
6134
+ }
6027
6135
 
6136
+ private generateCapabilityAnalysis(vendorName: string, safeguard: SafeguardElement, responseText: string,
6137
+ claimedCapability: string, qualityAssessment: any): VendorAnalysis {
6138
+ // Generate the new capability-focused analysis result
6028
6139
  return {
6029
6140
  vendor: vendorName,
6030
6141
  safeguardId: safeguard.id,
6031
6142
  safeguardTitle: safeguard.title,
6032
- capability: primaryCapability,
6143
+ capability: claimedCapability as 'full' | 'partial' | 'facilitates' | 'governance' | 'validates',
6033
6144
  capabilities: {
6034
- full: fullCapability,
6035
- partial: partialCapability,
6036
- facilitates: facilitatesCapability,
6037
- governance: governanceCapability,
6038
- validates: validatesCapability
6145
+ full: claimedCapability === 'full',
6146
+ partial: claimedCapability === 'partial',
6147
+ facilitates: claimedCapability === 'facilitates',
6148
+ governance: claimedCapability === 'governance',
6149
+ validates: claimedCapability === 'validates'
6039
6150
  },
6040
- confidence: Math.round(confidence),
6041
- reasoning: this.generateCapabilityReasoning(primaryCapability, fullCapability, partialCapability, governanceCapability, facilitatesCapability, validatesCapability, coreCoverage, subElementCoverage, safeguard, hasFacilitationPattern, hasNonImplementationLanguage),
6042
- evidence,
6043
- elementsCovered: {
6044
- coreRequirements: coreCoverage.coveredElements,
6045
- subTaxonomicalElements: subElementCoverage.coveredElements,
6046
- governanceElements: governanceCoverage.coveredElements,
6047
- implementationMethods: implementationCoverage.coveredElements
6048
- },
6049
- elementsNotCovered: {
6050
- coreRequirements: coreCoverage.uncoveredElements,
6051
- subTaxonomicalElements: subElementCoverage.uncoveredElements
6052
- }
6151
+ confidence: qualityAssessment.confidence,
6152
+ reasoning: this.generateCapabilityReasoning(claimedCapability, qualityAssessment, safeguard),
6153
+ evidence: qualityAssessment.evidence,
6154
+ // Note: elementsCovered is now less relevant in capability-focused analysis
6155
+ // We focus on tool capability rather than element coverage
6156
+ toolCapabilityDescription: this.generateToolCapabilityDescription(claimedCapability, qualityAssessment),
6157
+ recommendedUse: this.generateRecommendedUse(claimedCapability, safeguard)
6053
6158
  };
6054
6159
  }
6055
6160
 
6161
+ private generateCapabilityReasoning(claimedCapability: string, qualityAssessment: any, safeguard: SafeguardElement): string {
6162
+ const capabilityDescriptions = {
6163
+ full: "directly implements the core functionality of this safeguard",
6164
+ partial: "implements limited aspects of this safeguard with clear scope boundaries",
6165
+ facilitates: "enhances or enables the implementation of this safeguard by others",
6166
+ governance: "provides governance, policy, and oversight capabilities for this safeguard",
6167
+ validates: "provides evidence, audit, and compliance validation for this safeguard"
6168
+ };
6169
+
6170
+ const qualityDescriptor = qualityAssessment.quality;
6171
+ const description = capabilityDescriptions[claimedCapability as keyof typeof capabilityDescriptions];
6172
+
6173
+ return `This tool ${description} with ${qualityDescriptor} capability quality. ${qualityAssessment.evidence.length > 0 ? 'Evidence: ' + qualityAssessment.evidence.join('; ') : ''}`;
6174
+ }
6175
+
6176
+ private generateToolCapabilityDescription(claimedCapability: string, qualityAssessment: any): string {
6177
+ const roleDescriptions = {
6178
+ full: "Core Implementation Tool - Directly performs the safeguard functionality",
6179
+ partial: "Focused Implementation Tool - Performs specific aspects of the safeguard",
6180
+ facilitates: "Enablement Tool - Helps organizations implement the safeguard more effectively",
6181
+ governance: "Governance Tool - Manages policies, processes, and oversight for the safeguard",
6182
+ validates: "Compliance Tool - Provides audit, evidence, and validation capabilities"
6183
+ };
6184
+
6185
+ return roleDescriptions[claimedCapability as keyof typeof roleDescriptions] || "Support Tool";
6186
+ }
6187
+
6188
+ private generateRecommendedUse(claimedCapability: string, safeguard: SafeguardElement): string {
6189
+ const recommendations = {
6190
+ full: `Use as primary implementation tool for ${safeguard.title}. Ensure proper configuration and integration.`,
6191
+ partial: `Use as part of a multi-tool strategy for ${safeguard.title}. Supplement with additional capabilities as needed.`,
6192
+ facilitates: `Use to enhance existing safeguard implementation. Combine with direct implementation tools.`,
6193
+ governance: `Use for policy management and governance oversight. Pair with implementation and validation tools.`,
6194
+ validates: `Use for compliance monitoring and evidence collection. Combine with implementation tools for complete coverage.`
6195
+ };
6196
+
6197
+ return recommendations[claimedCapability as keyof typeof recommendations] || "Evaluate specific use case alignment.";
6198
+ }
6199
+
6056
6200
  private calculateKeywordScore(text: string, keywords: string[]): number {
6057
- let score = 0;
6058
- let matches = 0;
6201
+ let matchedKeywords = 0;
6202
+ let totalMatches = 0;
6059
6203
 
6060
6204
  keywords.forEach(keyword => {
6061
6205
  const regex = new RegExp(keyword.replace(/\s+/g, '\\s+'), 'gi');
6062
6206
  const keywordMatches = (text.match(regex) || []).length;
6063
6207
  if (keywordMatches > 0) {
6064
- matches++;
6065
- score += keywordMatches;
6208
+ matchedKeywords++;
6209
+ totalMatches += keywordMatches;
6066
6210
  }
6067
6211
  });
6068
6212
 
6069
- return matches > 0 ? score / text.split(' ').length : 0;
6213
+ // Return percentage of keywords that were found, with bonus for multiple matches
6214
+ const baseScore = matchedKeywords / keywords.length;
6215
+ const matchBonus = Math.min(totalMatches * 0.1, 0.5); // Up to 50% bonus for multiple matches
6216
+ return Math.min(baseScore + matchBonus, 1.0);
6070
6217
  }
6071
6218
 
6072
6219
  private analyzeElementCoverage(text: string, elements: string[]): {
@@ -6208,76 +6355,6 @@ export class GRCAnalysisServer {
6208
6355
  return reasons.join('. ');
6209
6356
  }
6210
6357
 
6211
- private generateCapabilityReasoning(
6212
- primaryCapability: string,
6213
- full: boolean,
6214
- partial: boolean,
6215
- governance: boolean,
6216
- facilitates: boolean,
6217
- validates: boolean,
6218
- coreCoverage: any,
6219
- subElementCoverage: any,
6220
- safeguard: SafeguardElement,
6221
- hasFacilitationPattern: boolean = false,
6222
- hasNonImplementationLanguage: boolean = false
6223
- ): string {
6224
- const reasons = [];
6225
-
6226
- // Primary capability explanation
6227
- switch (primaryCapability) {
6228
- case 'full':
6229
- reasons.push(`Provides FULL coverage of ${safeguard.title} - directly implements all core and sub-taxonomical elements`);
6230
- break;
6231
- case 'partial':
6232
- reasons.push(`Provides PARTIAL coverage of ${safeguard.title} - directly implements some but not all core and sub-taxonomical elements`);
6233
- break;
6234
- case 'facilitates':
6235
- if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
6236
- reasons.push(`FACILITATES ${safeguard.title} by creating governance frameworks, policy infrastructure, and compliance processes that enable organizations to implement the control effectively`);
6237
- } else {
6238
- reasons.push(`FACILITATES ${safeguard.title} through data integration, automation, or technical capabilities that support implementation`);
6239
- }
6240
- break;
6241
- case 'governance':
6242
- reasons.push(`Provides GOVERNANCE capabilities for ${safeguard.title} through centralized policy management, process controls, and compliance oversight`);
6243
- break;
6244
- case 'validates':
6245
- reasons.push(`VALIDATES ${safeguard.title} implementation through evidence collection, compliance reporting, and audit capabilities`);
6246
- break;
6247
- default:
6248
- reasons.push(`No clear capability identified for ${safeguard.title}`);
6249
- }
6250
-
6251
- // Coverage details
6252
- if (coreCoverage.coveredElements.length > 0) {
6253
- reasons.push(`Core elements addressed: ${coreCoverage.coveredElements.length}/${safeguard.coreRequirements.length}`);
6254
- }
6255
- if (subElementCoverage.coveredElements.length > 0) {
6256
- reasons.push(`Sub-taxonomical elements addressed: ${subElementCoverage.coveredElements.length}/${safeguard.subTaxonomicalElements.length}`);
6257
- }
6258
-
6259
- // Additional context for facilitation tools
6260
- if (primaryCapability === 'facilitates') {
6261
- if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
6262
- reasons.push(`Note: This type of facilitation tool works alongside technical implementation solutions (asset scanners, MDM tools, etc.) to provide comprehensive control coverage`);
6263
- }
6264
- if (hasNonImplementationLanguage) {
6265
- reasons.push(`Tool explicitly enables compliance through governance/process rather than direct technical implementation`);
6266
- }
6267
- }
6268
-
6269
- // Multi-capability products
6270
- const capabilityFlags = [governance, facilitates, validates].filter(Boolean);
6271
- if (capabilityFlags.length > 1) {
6272
- const capabilities = [];
6273
- if (governance) capabilities.push('governance');
6274
- if (facilitates) capabilities.push('facilitates');
6275
- if (validates) capabilities.push('validates');
6276
- reasons.push(`Multi-capability product with: ${capabilities.join(', ')}`);
6277
- }
6278
-
6279
- return reasons.join('. ');
6280
- }
6281
6358
 
6282
6359
  private validateClaim(claim: string, analysis: VendorAnalysis, capabilities: string[], safeguard: SafeguardElement) {
6283
6360
  const validation = {
@@ -6293,16 +6370,14 @@ export class GRCAnalysisServer {
6293
6370
  validation.coverageClaimValid = meetsFullCriteria;
6294
6371
 
6295
6372
  if (!meetsFullCriteria) {
6296
- const totalElements = safeguard.coreRequirements.length + safeguard.subTaxonomicalElements.length;
6297
- const coveredElements = analysis.elementsCovered.coreRequirements.length + analysis.elementsCovered.subTaxonomicalElements.length;
6298
- validation.gaps.push(`FULL coverage claim not supported: Only ${coveredElements}/${totalElements} core and sub-taxonomical elements covered`);
6373
+ validation.gaps.push(`FULL implementation capability claim not supported: Tool does not demonstrate direct implementation of core safeguard functionality`);
6299
6374
  }
6300
6375
  } else if (claim === 'PARTIAL') {
6301
6376
  const meetsPartialCriteria = analysis.capabilities.partial || analysis.capabilities.full;
6302
6377
  validation.coverageClaimValid = meetsPartialCriteria;
6303
6378
 
6304
6379
  if (!meetsPartialCriteria) {
6305
- validation.gaps.push(`PARTIAL coverage claim questionable: No core or sub-taxonomical elements clearly addressed`);
6380
+ validation.gaps.push(`PARTIAL implementation capability claim questionable: No core or sub-taxonomical elements clearly addressed`);
6306
6381
  }
6307
6382
  }
6308
6383
 
@@ -6348,13 +6423,15 @@ export class GRCAnalysisServer {
6348
6423
  } else {
6349
6424
  validation.recommendations.push(`Consider requesting additional information about: ${validation.gaps.join(', ')}`);
6350
6425
 
6351
- // Specific recommendations based on gaps
6352
- if (analysis.elementsNotCovered.coreRequirements.length > 0) {
6353
- validation.recommendations.push(`Request details on how these core elements are addressed: ${analysis.elementsNotCovered.coreRequirements.slice(0,3).join(', ')}${analysis.elementsNotCovered.coreRequirements.length > 3 ? '...' : ''}`);
6354
- }
6355
-
6356
- if (analysis.elementsNotCovered.subTaxonomicalElements.length > 0) {
6357
- validation.recommendations.push(`Ask for specifics on these sub-taxonomical elements: ${analysis.elementsNotCovered.subTaxonomicalElements.slice(0,3).join(', ')}${analysis.elementsNotCovered.subTaxonomicalElements.length > 3 ? '...' : ''}`);
6426
+ // Capability-based recommendations
6427
+ if (analysis.capability === 'facilitates') {
6428
+ validation.recommendations.push('Consider pairing with direct implementation tools for complete safeguard coverage');
6429
+ } else if (analysis.capability === 'partial') {
6430
+ validation.recommendations.push('Evaluate scope limitations and identify complementary tools for full coverage');
6431
+ } else if (analysis.capability === 'governance') {
6432
+ validation.recommendations.push('Combine with technical implementation tools for complete safeguard execution');
6433
+ } else if (analysis.capability === 'validates') {
6434
+ validation.recommendations.push('Pair with implementation tools to ensure both execution and validation coverage');
6358
6435
  }
6359
6436
 
6360
6437
  if (!analysis.capabilities.validates && capabilities.includes('Validates')) {
@@ -6368,10 +6445,12 @@ export class GRCAnalysisServer {
6368
6445
  private async validateVendorMapping(args: any) {
6369
6446
  const { vendor_name = 'Unknown Vendor', safeguard_id, claimed_capability, supporting_text } = args;
6370
6447
 
6448
+ // Input validation
6449
+ this.validateSafeguardId(safeguard_id);
6450
+ this.validateTextInput(supporting_text, 'Supporting text');
6451
+ this.validateCapability(claimed_capability);
6452
+
6371
6453
  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
6454
 
6376
6455
  const validation = this.validateCapabilityClaim(
6377
6456
  vendor_name,
@@ -6399,7 +6478,7 @@ export class GRCAnalysisServer {
6399
6478
  const text = supportingText.toLowerCase();
6400
6479
 
6401
6480
  // Detect tool type and validate domain match
6402
- const detectedToolType = this.detectToolType(supportingText);
6481
+ const detectedToolType = this.detectToolType(supportingText, safeguard.id);
6403
6482
  const domainValidation = this.validateDomainMatch(safeguard.id, claimedCapability, detectedToolType);
6404
6483
 
6405
6484
  // Adjust capability if domain mismatch detected
@@ -6411,28 +6490,15 @@ export class GRCAnalysisServer {
6411
6490
  effectiveCapability = domainValidation.adjusted_capability!;
6412
6491
  }
6413
6492
 
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);
6493
+ // Perform capability-focused analysis of the supporting text
6494
+ const actualAnalysis = this.performCapabilityAnalysis(vendorName, safeguard, supportingText);
6421
6495
 
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(
6496
+ // Validate claimed capability against actual capability analysis and domain requirements
6497
+ const validation = this.assessCapabilityClaimAlignment(
6498
+ claimedCapability,
6431
6499
  effectiveCapability,
6432
- actualAnalysis,
6433
- corePercentage,
6434
- subElementPercentage,
6435
- governancePercentage,
6500
+ actualAnalysis,
6501
+ domainValidation,
6436
6502
  text
6437
6503
  );
6438
6504
 
@@ -6451,12 +6517,10 @@ export class GRCAnalysisServer {
6451
6517
  claimed_capability: claimedCapability,
6452
6518
  validation_status: validation.status,
6453
6519
  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
- },
6520
+ actual_capability_detected: actualAnalysis.capability,
6521
+ capability_confidence: actualAnalysis.confidence,
6522
+ tool_capability_description: actualAnalysis.toolCapabilityDescription,
6523
+ recommended_use: actualAnalysis.recommendedUse,
6460
6524
  domain_validation: {
6461
6525
  required_tool_type: domainValidation.required_tool_types.join('/'),
6462
6526
  detected_tool_type: detectedToolType,
@@ -6471,17 +6535,15 @@ export class GRCAnalysisServer {
6471
6535
  };
6472
6536
  }
6473
6537
 
6474
- private assessClaimAlignment(
6538
+ private assessCapabilityClaimAlignment(
6475
6539
  claimedCapability: string,
6540
+ effectiveCapability: string,
6476
6541
  actualAnalysis: VendorAnalysis,
6477
- corePercentage: number,
6478
- subElementPercentage: number,
6479
- governancePercentage: number,
6542
+ domainValidation: any,
6480
6543
  text: string
6481
6544
  ): {
6482
6545
  status: 'SUPPORTED' | 'QUESTIONABLE' | 'UNSUPPORTED';
6483
6546
  confidence: number;
6484
- languageConsistency: number;
6485
6547
  gaps: string[];
6486
6548
  strengths: string[];
6487
6549
  recommendations: string[];
@@ -6490,113 +6552,42 @@ export class GRCAnalysisServer {
6490
6552
  const gaps: string[] = [];
6491
6553
  const strengths: string[] = [];
6492
6554
  const recommendations: string[] = [];
6493
- let languageConsistency = 0;
6555
+
6556
+ // Compare claimed capability with what we actually detected
6557
+ const claimedLower = claimedCapability.toLowerCase();
6558
+ const effectiveLower = effectiveCapability.toLowerCase();
6559
+ const actualCapability = actualAnalysis.capability;
6560
+
6494
6561
  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;
6562
+
6563
+ // Check if claim aligns with actual analysis
6564
+ if (claimedLower === actualCapability) {
6565
+ alignmentScore = actualAnalysis.confidence;
6566
+ strengths.push(`Claimed capability '${claimedCapability}' aligns with detected capability`);
6567
+ strengths.push(`Tool demonstrates appropriate ${actualAnalysis.toolCapabilityDescription.toLowerCase()}`);
6568
+ } else if (effectiveLower === actualCapability) {
6569
+ // Domain validation adjusted the capability and it matches the analysis
6570
+ alignmentScore = Math.max(actualAnalysis.confidence - 20, 30);
6571
+ gaps.push(`Original claim '${claimedCapability}' doesn't match tool type, adjusted to '${effectiveCapability}'`);
6572
+ strengths.push(`Adjusted capability '${effectiveCapability}' aligns with tool analysis`);
6573
+ } else {
6574
+ // Neither claimed nor effective capability matches the analysis
6575
+ alignmentScore = Math.max(actualAnalysis.confidence - 40, 10);
6576
+ gaps.push(`Claimed capability '${claimedCapability}' doesn't align with detected capability '${actualCapability}'`);
6577
+ gaps.push(`Tool appears to be: ${actualAnalysis.toolCapabilityDescription}`);
6597
6578
  }
6598
-
6599
- // Determine overall status
6579
+
6580
+ // Add evidence from the capability analysis
6581
+ if (actualAnalysis.evidence && actualAnalysis.evidence.length > 0) {
6582
+ strengths.push(`Supporting evidence: ${actualAnalysis.evidence.slice(0, 2).join('; ')}`);
6583
+ }
6584
+
6585
+ // Domain validation feedback
6586
+ if (!domainValidation.domain_match) {
6587
+ gaps.push(`Tool type '${domainValidation.detected_tool_type}' not appropriate for this safeguard domain`);
6588
+ }
6589
+
6590
+ // Determine overall status based on alignment score
6600
6591
  let status: 'SUPPORTED' | 'QUESTIONABLE' | 'UNSUPPORTED';
6601
6592
  if (alignmentScore >= 70) {
6602
6593
  status = 'SUPPORTED';
@@ -6605,21 +6596,23 @@ export class GRCAnalysisServer {
6605
6596
  } else {
6606
6597
  status = 'UNSUPPORTED';
6607
6598
  }
6608
-
6609
- // Generate recommendations
6610
- if (gaps.length > 0) {
6611
- recommendations.push('Address identified gaps to strengthen capability claim');
6612
- }
6599
+
6600
+ // Generate capability-focused recommendations
6601
+ recommendations.push(actualAnalysis.recommendedUse);
6602
+
6613
6603
  if (status === 'QUESTIONABLE') {
6614
- recommendations.push('Provide additional evidence or clarify scope to support claim');
6604
+ recommendations.push('Consider clarifying tool capabilities or adjusting capability claim');
6615
6605
  }
6616
-
6617
- const feedback = this.generateValidationFeedback(claimedCapability, status, gaps, strengths, alignmentScore);
6606
+
6607
+ if (!domainValidation.domain_match) {
6608
+ recommendations.push(`For ${actualCapability.toUpperCase()} capability, focus on how the tool ${actualCapability === 'facilitates' ? 'enables and enhances' : actualCapability === 'governance' ? 'manages policies and processes for' : actualCapability === 'validates' ? 'provides evidence and reporting on' : 'directly implements'} this safeguard`);
6609
+ }
6610
+
6611
+ const feedback = this.generateCapabilityValidationFeedback(claimedCapability, effectiveCapability, actualCapability, status, alignmentScore, domainValidation);
6618
6612
 
6619
6613
  return {
6620
6614
  status,
6621
6615
  confidence: Math.round(alignmentScore),
6622
- languageConsistency: Math.round(languageConsistency),
6623
6616
  gaps,
6624
6617
  strengths,
6625
6618
  recommendations,
@@ -6685,73 +6678,153 @@ export class GRCAnalysisServer {
6685
6678
  return this.calculateKeywordScore(text, validationKeywords) * 100;
6686
6679
  }
6687
6680
 
6688
- private detectToolType(text: string): string {
6681
+ private detectToolType(text: string, safeguardId?: string): string {
6689
6682
  const lowerText = text.toLowerCase();
6690
6683
 
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
- ];
6684
+ // Enhanced keyword definitions with scoring weights and context
6685
+ const toolTypePatterns = {
6686
+ 'inventory': {
6687
+ primary: [
6688
+ 'asset management', 'inventory management', 'cmdb', 'configuration management database',
6689
+ 'asset discovery', 'hardware inventory', 'software inventory', 'device inventory',
6690
+ 'asset tracking', 'it asset management', 'endpoint discovery', 'asset lifecycle'
6691
+ ],
6692
+ secondary: [
6693
+ 'inventory', 'discovery', 'device management', 'endpoint management',
6694
+ 'configuration management', 'asset database', 'equipment tracking'
6695
+ ],
6696
+ weight: { primary: 3, secondary: 1 }
6697
+ },
6698
+ 'identity_management': {
6699
+ primary: [
6700
+ 'identity management', 'iam', 'active directory', 'identity provider',
6701
+ 'single sign-on', 'sso', 'multi-factor authentication', 'mfa',
6702
+ 'user management', 'account management', 'directory service'
6703
+ ],
6704
+ secondary: [
6705
+ 'ldap', 'authentication', 'access management', 'identity access management',
6706
+ 'user directory', 'account lifecycle', 'privileged access'
6707
+ ],
6708
+ weight: { primary: 3, secondary: 1 }
6709
+ },
6710
+ 'vulnerability_management': {
6711
+ primary: [
6712
+ 'vulnerability management', 'vulnerability scanner', 'patch management',
6713
+ 'security scanning', 'vulnerability assessment', 'penetration testing'
6714
+ ],
6715
+ secondary: [
6716
+ 'vuln scan', 'security scanner', 'network scanner', 'scanning capabilities',
6717
+ 'security assessment', 'vulnerability scanning', 'patch deployment'
6718
+ ],
6719
+ weight: { primary: 3, secondary: 1 }
6720
+ },
6721
+ 'threat_intelligence': {
6722
+ primary: [
6723
+ 'threat intelligence', 'cyber threat intelligence', 'threat intel',
6724
+ 'threat feed', 'ioc feed', 'security intelligence', 'threat data'
6725
+ ],
6726
+ secondary: [
6727
+ 'enrichment', 'data feed', 'contextual data', 'risk intelligence',
6728
+ 'threat indicators', 'intelligence platform', 'threat correlation'
6729
+ ],
6730
+ weight: { primary: 3, secondary: 1 }
6731
+ },
6732
+ 'network_security': {
6733
+ primary: [
6734
+ 'firewall', 'network access control', 'nac', 'intrusion detection',
6735
+ 'network security', 'network segmentation'
6736
+ ],
6737
+ secondary: [
6738
+ 'network monitoring', 'traffic analysis', 'perimeter security',
6739
+ 'network protection', 'network filtering'
6740
+ ],
6741
+ weight: { primary: 3, secondary: 1 }
6742
+ },
6743
+ 'governance': {
6744
+ primary: [
6745
+ 'grc', 'governance risk compliance', 'compliance management',
6746
+ 'policy management', 'risk management', 'audit management'
6747
+ ],
6748
+ secondary: [
6749
+ 'governance', 'compliance platform', 'policy enforcement',
6750
+ 'regulatory compliance', 'framework management'
6751
+ ],
6752
+ weight: { primary: 3, secondary: 1 }
6753
+ },
6754
+ 'security_analytics': {
6755
+ primary: [
6756
+ 'siem', 'security information event management', 'security analytics',
6757
+ 'soar', 'security orchestration', 'log management'
6758
+ ],
6759
+ secondary: [
6760
+ 'security monitoring', 'event correlation', 'log analysis',
6761
+ 'security intelligence', 'incident response platform'
6762
+ ],
6763
+ weight: { primary: 3, secondary: 1 }
6764
+ }
6765
+ };
6711
6766
 
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
- ];
6767
+ // Calculate scores for each tool type
6768
+ const toolScores: Record<string, number> = {};
6717
6769
 
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
- ];
6770
+ for (const [toolType, patterns] of Object.entries(toolTypePatterns)) {
6771
+ let score = 0;
6772
+
6773
+ // Check primary keywords
6774
+ for (const keyword of patterns.primary) {
6775
+ if (lowerText.includes(keyword)) {
6776
+ score += patterns.weight.primary;
6777
+ }
6778
+ }
6779
+
6780
+ // Check secondary keywords
6781
+ for (const keyword of patterns.secondary) {
6782
+ if (lowerText.includes(keyword)) {
6783
+ score += patterns.weight.secondary;
6784
+ }
6785
+ }
6786
+
6787
+ toolScores[toolType] = score;
6788
+ }
6724
6789
 
6725
- // GRC/Governance tools
6726
- const governanceKeywords = [
6727
- 'grc', 'governance', 'compliance management', 'policy management',
6728
- 'risk management', 'audit management', 'compliance platform'
6729
- ];
6790
+ // Apply safeguard-specific context weighting if provided
6791
+ if (safeguardId && toolScores) {
6792
+ const contextBonus = 1; // Small bonus for domain alignment
6793
+
6794
+ // Asset inventory safeguards (1.1, 1.2) favor inventory tools
6795
+ if (['1.1', '1.2'].includes(safeguardId) && toolScores['inventory'] > 0) {
6796
+ toolScores['inventory'] += contextBonus;
6797
+ }
6798
+
6799
+ // Account inventory safeguards (5.1, 5.2, 5.3) favor identity tools
6800
+ if (['5.1', '5.2', '5.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
6801
+ toolScores['identity_management'] += contextBonus;
6802
+ }
6803
+
6804
+ // Authentication safeguards (6.1, 6.2, 6.3) favor identity tools
6805
+ if (['6.1', '6.2', '6.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
6806
+ toolScores['identity_management'] += contextBonus;
6807
+ }
6808
+
6809
+ // Vulnerability safeguards (7.1-7.7) favor vulnerability management tools
6810
+ if (['7.1', '7.2', '7.3', '7.4', '7.5', '7.6', '7.7'].includes(safeguardId) && toolScores['vulnerability_management'] > 0) {
6811
+ toolScores['vulnerability_management'] += contextBonus;
6812
+ }
6813
+ }
6730
6814
 
6731
- // Security Analytics/SIEM tools
6732
- const analyticsKeywords = [
6733
- 'siem', 'security analytics', 'log management', 'security monitoring',
6734
- 'event correlation', 'security orchestration', 'soar'
6735
- ];
6815
+ // Find the tool type with highest score
6816
+ let maxScore = 0;
6817
+ let detectedType = 'unknown';
6736
6818
 
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';
6819
+ for (const [toolType, score] of Object.entries(toolScores)) {
6820
+ if (score > maxScore) {
6821
+ maxScore = score;
6822
+ detectedType = toolType;
6823
+ }
6752
6824
  }
6753
6825
 
6754
- return 'unknown';
6826
+ // Require minimum score threshold to avoid false positives
6827
+ return maxScore >= 2 ? detectedType : 'unknown';
6755
6828
  }
6756
6829
 
6757
6830
  private validateDomainMatch(
@@ -6785,7 +6858,7 @@ export class GRCAnalysisServer {
6785
6858
  required_tool_types: domainReq.required_tool_types,
6786
6859
  should_adjust_capability: true,
6787
6860
  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.`
6861
+ reasoning: `${domainReq.domain} safeguard requires ${domainReq.required_tool_types.join('/')} tool types for FULL/PARTIAL implementation capability. Detected tool type '${detectedToolType}' can only facilitate implementation.`
6789
6862
  };
6790
6863
  }
6791
6864
 
@@ -6799,6 +6872,38 @@ export class GRCAnalysisServer {
6799
6872
  };
6800
6873
  }
6801
6874
 
6875
+ private generateCapabilityValidationFeedback(
6876
+ claimedCapability: string,
6877
+ effectiveCapability: string,
6878
+ actualCapability: string,
6879
+ status: string,
6880
+ score: number,
6881
+ domainValidation: any
6882
+ ): string {
6883
+ let feedback = `Capability Validation: ${claimedCapability.toUpperCase()} claim is ${status} (${Math.round(score)}% confidence)\n\n`;
6884
+
6885
+ // Analysis summary
6886
+ feedback += `ANALYSIS:\n`;
6887
+ feedback += `• Claimed: ${claimedCapability.toUpperCase()}\n`;
6888
+ if (effectiveCapability !== claimedCapability) {
6889
+ feedback += `• Domain Adjusted: ${effectiveCapability.toUpperCase()} (${domainValidation.reasoning})\n`;
6890
+ }
6891
+ feedback += `• Detected: ${actualCapability.toUpperCase()}\n`;
6892
+ feedback += `• Tool Type: ${domainValidation.detected_tool_type}\n\n`;
6893
+
6894
+ // Assessment
6895
+ feedback += `ASSESSMENT: `;
6896
+ if (claimedCapability.toLowerCase() === actualCapability) {
6897
+ feedback += 'Claimed capability aligns perfectly with tool analysis.';
6898
+ } else if (effectiveCapability.toLowerCase() === actualCapability) {
6899
+ feedback += 'After domain validation adjustment, capability aligns with tool analysis.';
6900
+ } else {
6901
+ feedback += `Capability mismatch detected. Tool functions as ${actualCapability.toUpperCase()} rather than claimed ${claimedCapability.toUpperCase()}.`;
6902
+ }
6903
+
6904
+ return feedback;
6905
+ }
6906
+
6802
6907
  private generateValidationFeedback(
6803
6908
  claimedCapability: string,
6804
6909
  status: string,
@@ -6806,7 +6911,7 @@ export class GRCAnalysisServer {
6806
6911
  strengths: string[],
6807
6912
  score: number
6808
6913
  ): string {
6809
- let feedback = `Validation of ${claimedCapability.toUpperCase()} capability claim: ${status} (${Math.round(score)}% alignment)\n\n`;
6914
+ let feedback = `Validation of ${claimedCapability.toUpperCase()} capability role claim: ${status} (${Math.round(score)}% alignment)\n\n`;
6810
6915
 
6811
6916
  if (strengths.length > 0) {
6812
6917
  feedback += `STRENGTHS:\n${strengths.map(s => `• ${s}`).join('\n')}\n\n`;
@@ -6819,23 +6924,162 @@ export class GRCAnalysisServer {
6819
6924
  feedback += `ASSESSMENT: `;
6820
6925
  switch (status) {
6821
6926
  case 'SUPPORTED':
6822
- feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability.';
6927
+ feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability role.';
6823
6928
  break;
6824
6929
  case 'QUESTIONABLE':
6825
6930
  feedback += 'The vendor\'s evidence partially supports their claim but has notable gaps or inconsistencies.';
6826
6931
  break;
6827
6932
  case 'UNSUPPORTED':
6828
- feedback += 'The vendor\'s evidence does not adequately support their claimed capability.';
6933
+ feedback += 'The vendor\'s evidence does not adequately support their claimed capability role.';
6829
6934
  break;
6830
6935
  }
6831
6936
 
6832
6937
  return feedback;
6833
6938
  }
6834
6939
 
6940
+ // Enhanced error handling and formatting
6941
+ private formatErrorMessage(error: unknown, toolName: string): string {
6942
+ if (error instanceof Error) {
6943
+ // Production-friendly error messages
6944
+ switch (error.message) {
6945
+ case /^Safeguard .+ not found/.test(error.message) ? error.message : '':
6946
+ return `❌ Invalid safeguard ID. Use 'list_available_safeguards' to see available CIS Control safeguards.`;
6947
+ case /^Unknown tool/.test(error.message) ? error.message : '':
6948
+ return `❌ Tool '${toolName}' is not available. Available tools: analyze_vendor_response, validate_vendor_mapping, validate_coverage_claim, get_safeguard_details, list_available_safeguards.`;
6949
+ default:
6950
+ return `❌ Error in ${toolName}: ${error.message}`;
6951
+ }
6952
+ }
6953
+ return `❌ Unexpected error in ${toolName}: ${String(error)}`;
6954
+ }
6955
+
6956
+ // Performance monitoring and caching
6957
+ private performanceMetrics = {
6958
+ toolExecutionTimes: new Map<string, number[]>(),
6959
+ startTime: Date.now(),
6960
+ totalRequests: 0,
6961
+ errorCount: 0
6962
+ };
6963
+
6964
+ // Simple cache for safeguard details (most commonly requested data)
6965
+ private cache = {
6966
+ safeguardDetails: new Map<string, any>(),
6967
+ safeguardList: null as any,
6968
+ lastCacheCleanup: Date.now()
6969
+ };
6970
+
6971
+ private getCachedSafeguardDetails(safeguardId: string, includeExamples: boolean): any | null {
6972
+ const cacheKey = `${safeguardId}_${includeExamples}`;
6973
+ const cached = this.cache.safeguardDetails.get(cacheKey);
6974
+
6975
+ if (cached && (Date.now() - cached.timestamp < 5 * 60 * 1000)) { // 5 minute cache
6976
+ return cached.data;
6977
+ }
6978
+
6979
+ return null;
6980
+ }
6981
+
6982
+ private setCachedSafeguardDetails(safeguardId: string, includeExamples: boolean, data: any): void {
6983
+ const cacheKey = `${safeguardId}_${includeExamples}`;
6984
+ this.cache.safeguardDetails.set(cacheKey, {
6985
+ data,
6986
+ timestamp: Date.now()
6987
+ });
6988
+
6989
+ // Periodic cache cleanup to prevent memory leaks
6990
+ if (Date.now() - this.cache.lastCacheCleanup > 10 * 60 * 1000) { // 10 minutes
6991
+ this.cleanupCache();
6992
+ }
6993
+ }
6994
+
6995
+ private cleanupCache(): void {
6996
+ const now = Date.now();
6997
+ const maxAge = 10 * 60 * 1000; // 10 minutes
6998
+
6999
+ // Clean up safeguard details cache
7000
+ for (const [key, value] of this.cache.safeguardDetails.entries()) {
7001
+ if (now - value.timestamp > maxAge) {
7002
+ this.cache.safeguardDetails.delete(key);
7003
+ }
7004
+ }
7005
+
7006
+ this.cache.lastCacheCleanup = now;
7007
+ }
7008
+
7009
+ private recordToolExecution(toolName: string, executionTime: number) {
7010
+ this.performanceMetrics.totalRequests++;
7011
+
7012
+ if (!this.performanceMetrics.toolExecutionTimes.has(toolName)) {
7013
+ this.performanceMetrics.toolExecutionTimes.set(toolName, []);
7014
+ }
7015
+
7016
+ const times = this.performanceMetrics.toolExecutionTimes.get(toolName)!;
7017
+ times.push(executionTime);
7018
+
7019
+ // Keep only last 100 measurements for memory efficiency
7020
+ if (times.length > 100) {
7021
+ times.shift();
7022
+ }
7023
+ }
7024
+
7025
+ private getPerformanceStats(): string {
7026
+ const uptime = Date.now() - this.performanceMetrics.startTime;
7027
+ const avgTimes = Array.from(this.performanceMetrics.toolExecutionTimes.entries())
7028
+ .map(([tool, times]) => {
7029
+ const avg = times.reduce((a, b) => a + b, 0) / times.length;
7030
+ return `${tool}: ${avg.toFixed(2)}ms`;
7031
+ });
7032
+
7033
+ return `Performance Stats (Uptime: ${(uptime / 1000).toFixed(1)}s, Requests: ${this.performanceMetrics.totalRequests}, Errors: ${this.performanceMetrics.errorCount})\n${avgTimes.join(', ')}`;
7034
+ }
7035
+
7036
+ // Input validation and sanitization
7037
+ private validateSafeguardId(safeguardId: string): void {
7038
+ if (!safeguardId || typeof safeguardId !== 'string') {
7039
+ throw new Error('Safeguard ID is required and must be a string');
7040
+ }
7041
+
7042
+ if (!/^[0-9]+\.[0-9]+$/.test(safeguardId)) {
7043
+ throw new Error('Safeguard ID must be in format "X.Y" (e.g., "1.1", "5.1")');
7044
+ }
7045
+
7046
+ if (!CIS_SAFEGUARDS[safeguardId]) {
7047
+ throw new Error(`Safeguard ${safeguardId} not found`);
7048
+ }
7049
+ }
7050
+
7051
+ private validateTextInput(text: string, fieldName: string): void {
7052
+ if (!text || typeof text !== 'string') {
7053
+ throw new Error(`${fieldName} is required and must be a string`);
7054
+ }
7055
+
7056
+ if (text.length > 10000) {
7057
+ throw new Error(`${fieldName} must be less than 10,000 characters`);
7058
+ }
7059
+
7060
+ if (text.trim().length < 10) {
7061
+ throw new Error(`${fieldName} must contain at least 10 meaningful characters`);
7062
+ }
7063
+ }
7064
+
7065
+ private validateCapability(capability: string): void {
7066
+ const validCapabilities = ['full', 'partial', 'facilitates', 'governance', 'validates'];
7067
+ if (!validCapabilities.includes(capability.toLowerCase())) {
7068
+ throw new Error(`Invalid capability. Must be one of: ${validCapabilities.join(', ')}`);
7069
+ }
7070
+ }
7071
+
6835
7072
  async run() {
6836
7073
  const transport = new StdioServerTransport();
6837
7074
  await this.server.connect(transport);
6838
7075
  console.error('FrameworkMCP server running on stdio');
7076
+
7077
+ // Log performance stats every 5 minutes in production
7078
+ if (process.env.NODE_ENV === 'production') {
7079
+ setInterval(() => {
7080
+ console.error(`[FrameworkMCP] ${this.getPerformanceStats()}`);
7081
+ }, 5 * 60 * 1000);
7082
+ }
6839
7083
  }
6840
7084
  }
6841
7085