framework-mcp 1.1.1 → 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/dist/index.js CHANGED
@@ -2,6 +2,34 @@
2
2
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ // Domain-specific validation mapping
6
+ const SAFEGUARD_DOMAIN_REQUIREMENTS = {
7
+ "1.1": {
8
+ domain: "Asset Inventory",
9
+ required_tool_types: ["inventory", "asset_management", "cmdb", "discovery"],
10
+ description: "Only asset inventory and discovery tools can provide FULL/PARTIAL implementation capability"
11
+ },
12
+ "1.2": {
13
+ domain: "Asset Management",
14
+ required_tool_types: ["inventory", "asset_management", "network_security", "nac"],
15
+ description: "Asset management or network access control tools required for FULL/PARTIAL implementation capability"
16
+ },
17
+ "5.1": {
18
+ domain: "Account Management",
19
+ required_tool_types: ["identity_management", "iam", "directory", "account_management"],
20
+ description: "Identity and account management tools required for FULL/PARTIAL implementation capability"
21
+ },
22
+ "6.3": {
23
+ domain: "Authentication",
24
+ required_tool_types: ["mfa", "authentication", "identity_management", "iam"],
25
+ description: "Multi-factor authentication and identity tools required for FULL/PARTIAL implementation capability"
26
+ },
27
+ "7.1": {
28
+ domain: "Vulnerability Management",
29
+ required_tool_types: ["vulnerability_management", "vulnerability_scanner", "patch_management"],
30
+ description: "Vulnerability management and scanning tools required for FULL/PARTIAL implementation capability"
31
+ }
32
+ };
5
33
  // Enhanced CIS Controls Framework Data with color-coded categorization
6
34
  const CIS_SAFEGUARDS = {
7
35
  "1.1": {
@@ -5434,6 +5462,19 @@ const CIS_SAFEGUARDS = {
5434
5462
  };
5435
5463
  export class GRCAnalysisServer {
5436
5464
  constructor() {
5465
+ // Performance monitoring and caching
5466
+ this.performanceMetrics = {
5467
+ toolExecutionTimes: new Map(),
5468
+ startTime: Date.now(),
5469
+ totalRequests: 0,
5470
+ errorCount: 0
5471
+ };
5472
+ // Simple cache for safeguard details (most commonly requested data)
5473
+ this.cache = {
5474
+ safeguardDetails: new Map(),
5475
+ safeguardList: null,
5476
+ lastCacheCleanup: Date.now()
5477
+ };
5437
5478
  this.server = new Server({
5438
5479
  name: 'framework-mcp',
5439
5480
  version: '1.0.0',
@@ -5445,7 +5486,7 @@ export class GRCAnalysisServer {
5445
5486
  tools: [
5446
5487
  {
5447
5488
  name: 'analyze_vendor_response',
5448
- description: 'Analyze a vendor response for a specific CIS Control safeguard against the 4 GRC attributes with detailed sub-element coverage',
5489
+ 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',
5449
5490
  inputSchema: {
5450
5491
  type: 'object',
5451
5492
  properties: {
@@ -5460,7 +5501,7 @@ export class GRCAnalysisServer {
5460
5501
  },
5461
5502
  response_text: {
5462
5503
  type: 'string',
5463
- description: 'Vendor response text to analyze'
5504
+ description: 'Vendor response text describing their tool capabilities for the safeguard'
5464
5505
  }
5465
5506
  },
5466
5507
  required: ['vendor_name', 'safeguard_id', 'response_text']
@@ -5488,7 +5529,7 @@ export class GRCAnalysisServer {
5488
5529
  },
5489
5530
  {
5490
5531
  name: 'validate_coverage_claim',
5491
- description: 'Validate a vendor\'s coverage claim (FULL/PARTIAL) against specific safeguard requirements',
5532
+ description: 'Validate a vendor\'s implementation capability claim (FULL/PARTIAL) against specific safeguard requirements and evidence quality',
5492
5533
  inputSchema: {
5493
5534
  type: 'object',
5494
5535
  properties: {
@@ -5504,16 +5545,16 @@ export class GRCAnalysisServer {
5504
5545
  coverage_claim: {
5505
5546
  type: 'string',
5506
5547
  enum: ['FULL', 'PARTIAL'],
5507
- description: 'Vendor\'s coverage claim'
5548
+ description: 'Vendor\'s implementation capability claim (FULL = complete implementation, PARTIAL = limited scope implementation)'
5508
5549
  },
5509
5550
  response_text: {
5510
5551
  type: 'string',
5511
- description: 'Vendor response explaining their coverage'
5552
+ description: 'Vendor response explaining their implementation capabilities'
5512
5553
  },
5513
5554
  capabilities: {
5514
5555
  type: 'array',
5515
5556
  items: { type: 'string' },
5516
- description: 'List of vendor capabilities/attributes (Governance, Facilitates, Validates)'
5557
+ description: 'List of additional vendor capability types (Governance, Facilitates, Validates)'
5517
5558
  }
5518
5559
  },
5519
5560
  required: ['vendor_name', 'safeguard_id', 'coverage_claim', 'response_text', 'capabilities']
@@ -5540,7 +5581,7 @@ export class GRCAnalysisServer {
5540
5581
  },
5541
5582
  {
5542
5583
  name: 'validate_vendor_mapping',
5543
- 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',
5584
+ 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',
5544
5585
  inputSchema: {
5545
5586
  type: 'object',
5546
5587
  properties: {
@@ -5557,11 +5598,11 @@ export class GRCAnalysisServer {
5557
5598
  claimed_capability: {
5558
5599
  type: 'string',
5559
5600
  enum: ['full', 'partial', 'facilitates', 'governance', 'validates'],
5560
- description: 'Vendor\'s claimed capability mapping for this safeguard'
5601
+ description: 'Vendor\'s claimed capability role: full (complete implementation), partial (limited implementation), facilitates (enables/enhances), governance (policies/processes), validates (evidence/reporting)'
5561
5602
  },
5562
5603
  supporting_text: {
5563
5604
  type: 'string',
5564
- description: 'Vendor\'s supporting text blob explaining how they meet the claimed capability'
5605
+ description: 'Vendor\'s supporting evidence explaining how their tool fulfills the claimed capability role'
5565
5606
  }
5566
5607
  },
5567
5608
  required: ['safeguard_id', 'claimed_capability', 'supporting_text']
@@ -5571,28 +5612,45 @@ export class GRCAnalysisServer {
5571
5612
  }));
5572
5613
  this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
5573
5614
  const { name, arguments: args } = request.params;
5615
+ const startTime = Date.now();
5574
5616
  try {
5617
+ let result;
5575
5618
  switch (name) {
5576
5619
  case 'analyze_vendor_response':
5577
- return await this.analyzeVendorResponse(args);
5620
+ result = await this.analyzeVendorResponse(args);
5621
+ break;
5578
5622
  case 'get_safeguard_details':
5579
- return await this.getSafeguardDetails(args);
5623
+ result = await this.getSafeguardDetails(args);
5624
+ break;
5580
5625
  case 'validate_coverage_claim':
5581
- return await this.validateCoverageClaim(args);
5626
+ result = await this.validateCoverageClaim(args);
5627
+ break;
5582
5628
  case 'list_available_safeguards':
5583
- return await this.listAvailableSafeguards(args);
5629
+ result = await this.listAvailableSafeguards(args);
5630
+ break;
5584
5631
  case 'validate_vendor_mapping':
5585
- return await this.validateVendorMapping(args);
5632
+ result = await this.validateVendorMapping(args);
5633
+ break;
5586
5634
  default:
5587
5635
  throw new Error(`Unknown tool: ${name}`);
5588
5636
  }
5637
+ // Record successful execution time
5638
+ const executionTime = Date.now() - startTime;
5639
+ this.recordToolExecution(name, executionTime);
5640
+ return result;
5589
5641
  }
5590
5642
  catch (error) {
5643
+ // Record error and performance metrics
5644
+ this.performanceMetrics.errorCount++;
5645
+ const executionTime = Date.now() - startTime;
5646
+ this.recordToolExecution(`${name}_error`, executionTime);
5647
+ const errorMessage = this.formatErrorMessage(error, name);
5648
+ console.error(`[FrameworkMCP] Tool execution error: ${name}`, error);
5591
5649
  return {
5592
5650
  content: [
5593
5651
  {
5594
5652
  type: 'text',
5595
- text: `Error: ${error instanceof Error ? error.message : String(error)}`,
5653
+ text: errorMessage,
5596
5654
  },
5597
5655
  ],
5598
5656
  };
@@ -5601,10 +5659,14 @@ export class GRCAnalysisServer {
5601
5659
  }
5602
5660
  async getSafeguardDetails(args) {
5603
5661
  const { safeguard_id, include_examples = true } = args;
5604
- const safeguard = CIS_SAFEGUARDS[safeguard_id];
5605
- if (!safeguard) {
5606
- throw new Error(`Safeguard ${safeguard_id} not found. Use list_available_safeguards to see available safeguards.`);
5662
+ // Input validation
5663
+ this.validateSafeguardId(safeguard_id);
5664
+ // Check cache first
5665
+ const cached = this.getCachedSafeguardDetails(safeguard_id, include_examples);
5666
+ if (cached) {
5667
+ return cached;
5607
5668
  }
5669
+ const safeguard = CIS_SAFEGUARDS[safeguard_id];
5608
5670
  const result = {
5609
5671
  ...safeguard,
5610
5672
  elementBreakdown: {
@@ -5632,7 +5694,7 @@ export class GRCAnalysisServer {
5632
5694
  })
5633
5695
  }
5634
5696
  };
5635
- return {
5697
+ const response = {
5636
5698
  content: [
5637
5699
  {
5638
5700
  type: 'text',
@@ -5640,9 +5702,19 @@ export class GRCAnalysisServer {
5640
5702
  },
5641
5703
  ],
5642
5704
  };
5705
+ // Cache the result for future requests
5706
+ this.setCachedSafeguardDetails(safeguard_id, include_examples, response);
5707
+ return response;
5643
5708
  }
5644
5709
  async listAvailableSafeguards(args) {
5645
5710
  const { implementation_group, security_function } = args;
5711
+ // Check cache for complete safeguard list (only if no filters applied)
5712
+ if (!implementation_group && !security_function && this.cache.safeguardList) {
5713
+ const cacheAge = Date.now() - this.cache.safeguardList.timestamp;
5714
+ if (cacheAge < 10 * 60 * 1000) { // 10 minute cache for safeguard list
5715
+ return this.cache.safeguardList.data;
5716
+ }
5717
+ }
5646
5718
  let safeguards = Object.values(CIS_SAFEGUARDS);
5647
5719
  if (implementation_group) {
5648
5720
  safeguards = safeguards.filter(s => s.implementationGroup === implementation_group);
@@ -5665,7 +5737,7 @@ export class GRCAnalysisServer {
5665
5737
  securityFunction: s.securityFunction
5666
5738
  }))
5667
5739
  };
5668
- return {
5740
+ const response = {
5669
5741
  content: [
5670
5742
  {
5671
5743
  type: 'text',
@@ -5673,14 +5745,25 @@ export class GRCAnalysisServer {
5673
5745
  },
5674
5746
  ],
5675
5747
  };
5748
+ // Cache the complete list if no filters were applied
5749
+ if (!implementation_group && !security_function) {
5750
+ this.cache.safeguardList = {
5751
+ data: response,
5752
+ timestamp: Date.now()
5753
+ };
5754
+ }
5755
+ return response;
5676
5756
  }
5677
5757
  async analyzeVendorResponse(args) {
5678
5758
  const { vendor_name, safeguard_id, response_text } = args;
5679
- const safeguard = CIS_SAFEGUARDS[safeguard_id];
5680
- if (!safeguard) {
5681
- throw new Error(`Safeguard ${safeguard_id} not found. Available safeguards: ${Object.keys(CIS_SAFEGUARDS).join(', ')}`);
5759
+ // Input validation
5760
+ this.validateSafeguardId(safeguard_id);
5761
+ this.validateTextInput(response_text, 'Response text');
5762
+ if (!vendor_name || typeof vendor_name !== 'string' || vendor_name.trim().length === 0) {
5763
+ throw new Error('Vendor name is required');
5682
5764
  }
5683
- const analysis = this.performEnhancedSafeguardAnalysis(vendor_name, safeguard, response_text);
5765
+ const safeguard = CIS_SAFEGUARDS[safeguard_id];
5766
+ const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
5684
5767
  return {
5685
5768
  content: [
5686
5769
  {
@@ -5696,7 +5779,7 @@ export class GRCAnalysisServer {
5696
5779
  if (!safeguard) {
5697
5780
  throw new Error(`Safeguard ${safeguard_id} not found`);
5698
5781
  }
5699
- const analysis = this.performEnhancedSafeguardAnalysis(vendor_name, safeguard, response_text);
5782
+ const analysis = this.performCapabilityAnalysis(vendor_name, safeguard, response_text);
5700
5783
  // Validate the coverage claim
5701
5784
  const validation = this.validateClaim(coverage_claim, analysis, capabilities, safeguard);
5702
5785
  return {
@@ -5715,163 +5798,242 @@ export class GRCAnalysisServer {
5715
5798
  ],
5716
5799
  };
5717
5800
  }
5718
- performEnhancedSafeguardAnalysis(vendorName, safeguard, responseText) {
5801
+ performCapabilityAnalysis(vendorName, safeguard, responseText) {
5719
5802
  const text = responseText.toLowerCase();
5720
- // Capability detection keywords
5721
- const governanceKeywords = [
5803
+ // Step 1: Determine what type of capability this tool is claiming
5804
+ const claimedCapability = this.determineClaimedCapability(text, safeguard);
5805
+ // Step 2: Assess how well the tool executes that specific capability type
5806
+ const qualityAssessment = this.assessCapabilityQuality(text, safeguard, claimedCapability);
5807
+ // Step 3: Generate capability-focused analysis
5808
+ return this.generateCapabilityAnalysis(vendorName, safeguard, responseText, claimedCapability, qualityAssessment);
5809
+ }
5810
+ determineClaimedCapability(text, safeguard) {
5811
+ // Capability detection keywords - focused on what the tool DOES, not what elements it covers
5812
+ const governanceIndicators = [
5722
5813
  'policy', 'policies', 'manage', 'process', 'workflow', 'governance', 'grc',
5723
5814
  'compliance management', 'documented', 'establish', 'maintain', 'procedure',
5724
5815
  'control', 'controls', 'framework', 'standard', 'enterprise risk management',
5725
5816
  'centralized management', 'oversight'
5726
5817
  ];
5727
- const facilitatesKeywords = [
5728
- // Technical facilitation (original keywords)
5818
+ const facilitatesIndicators = [
5729
5819
  'improve', 'enhance', 'optimize', 'faster', 'better', 'stronger', 'automate',
5730
5820
  'streamline', 'efficiency', 'facilitate', 'support', 'enable', 'accelerate',
5731
5821
  'api', 'integration', 'data', 'export', 'import', 'sync', 'feed',
5732
- // Data provision and enrichment
5733
5822
  'provides data', 'data source', 'data feeds', 'enrichment', 'data enrichment',
5734
5823
  'supplemental data', 'additional data', 'contextual data', 'threat data',
5735
5824
  'intelligence feeds', 'data aggregation', 'data collection', 'data gathering',
5736
5825
  'feeds data', 'populates', 'informs', 'enriches', 'supplements',
5737
- // Governance/process facilitation (new keywords for tools like Upolicy)
5738
5826
  'enables compliance', 'facilitates implementation', 'supports compliance',
5739
5827
  'creates framework', 'enables organizations', 'infrastructure', 'foundation',
5740
- 'compliance infrastructure', 'audit infrastructure', 'policy framework',
5741
- 'enables effective', 'working together', 'comprehensive coverage',
5742
5828
  'template', 'templates', 'workflow automation', 'orchestration'
5743
5829
  ];
5744
- const validatesKeywords = [
5830
+ const validatesIndicators = [
5745
5831
  'audit', 'report', 'evidence', 'verify', 'validate', 'check', 'monitor',
5746
5832
  'compliance', 'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest',
5747
5833
  'dashboard', 'metrics', 'analytics', 'visibility', 'alert', 'attestation',
5748
5834
  'compliance tracking', 'audit trail', 'reporting capabilities', 'audit capabilities'
5749
5835
  ];
5750
- // Analyze element coverage (binary: covered or not)
5751
- const coreCoverage = this.analyzeBinaryElementCoverage(text, safeguard.coreRequirements);
5752
- const subElementCoverage = this.analyzeBinaryElementCoverage(text, safeguard.subTaxonomicalElements);
5753
- const governanceCoverage = this.analyzeBinaryElementCoverage(text, safeguard.governanceElements);
5754
- const implementationCoverage = this.analyzeBinaryElementCoverage(text, safeguard.implementationSuggestions);
5755
- // Enhanced capability detection with better scoring
5756
- const governanceScore = this.calculateKeywordScore(text, governanceKeywords);
5757
- const facilitatesScore = this.calculateKeywordScore(text, facilitatesKeywords);
5758
- const validatesScore = this.calculateKeywordScore(text, validatesKeywords);
5759
- const governanceCapability = governanceScore > 0.3;
5760
- const facilitatesCapability = facilitatesScore > 0.3;
5761
- const validatesCapability = validatesScore > 0.3;
5762
- // Check for specific facilitation patterns (tools that enable/support compliance)
5763
- const facilitationPatterns = [
5764
- 'enables compliance', 'facilitates implementation', 'creates framework',
5765
- 'policy framework', 'compliance infrastructure', 'audit infrastructure',
5766
- 'enables organizations', 'enables effective', 'working together',
5767
- 'creates the policy framework', 'enables organizations to implement',
5768
- 'facilitates implementation of', 'compliance infrastructure facilitates'
5769
- ];
5770
- const hasFacilitationPattern = facilitationPatterns.some(pattern => text.includes(pattern));
5771
- // Check for explicit non-implementation language
5772
- const nonImplementationPatterns = [
5773
- 'don\'t scan', 'don\'t catalog', 'doesn\'t scan', 'doesn\'t catalog',
5774
- 'not scan', 'not catalog', 'even though we don\'t', 'we don\'t directly',
5775
- 'rather than direct', 'instead of direct'
5776
- ];
5777
- const hasNonImplementationLanguage = nonImplementationPatterns.some(pattern => text.includes(pattern));
5778
- // Determine if full or partial coverage (based on core + sub-taxonomical elements WITHIN SCOPE)
5779
- // Full = addresses majority of core requirements + substantial sub-elements within their stated scope
5780
- // Partial = addresses some core requirements with clear scope boundaries
5781
- const corePercentage = safeguard.coreRequirements.length > 0 ?
5782
- (coreCoverage.coveredElements.length / safeguard.coreRequirements.length) * 100 : 0;
5783
- const subElementPercentage = safeguard.subTaxonomicalElements.length > 0 ?
5784
- (subElementCoverage.coveredElements.length / safeguard.subTaxonomicalElements.length) * 100 : 0;
5785
- let fullCapability = false;
5786
- let partialCapability = false;
5787
- // Full capability: High coverage of core requirements + reasonable sub-element coverage
5788
- if (corePercentage >= 70 && subElementPercentage >= 50) {
5789
- fullCapability = true;
5836
+ // Direct implementation indicators (tools that actually perform the safeguard)
5837
+ const implementationIndicators = this.getImplementationIndicators(safeguard.id);
5838
+ // Calculate keyword presence scores
5839
+ const governanceScore = this.calculateKeywordScore(text, governanceIndicators);
5840
+ const facilitatesScore = this.calculateKeywordScore(text, facilitatesIndicators);
5841
+ const validatesScore = this.calculateKeywordScore(text, validatesIndicators);
5842
+ const implementationScore = this.calculateKeywordScore(text, implementationIndicators);
5843
+ // Determine claimed capability based on strongest indicators and patterns
5844
+ if (implementationScore > 0.2 && implementationScore >= Math.max(facilitatesScore, governanceScore, validatesScore)) {
5845
+ // Tool claims to directly implement the safeguard
5846
+ return implementationScore > 0.5 ? 'full' : 'partial';
5790
5847
  }
5791
- // Partial capability: Moderate core coverage OR clear scope-limited implementation
5792
- else if (corePercentage >= 30 || (coreCoverage.coveredElements.length > 0 && subElementPercentage >= 20)) {
5793
- partialCapability = true;
5848
+ else if (governanceScore > 0.2 && governanceScore >= Math.max(facilitatesScore, validatesScore)) {
5849
+ return 'governance';
5794
5850
  }
5795
- // Enhanced primary capability logic
5796
- let primaryCapability = 'none';
5797
- if (fullCapability) {
5798
- primaryCapability = 'full';
5851
+ else if (validatesScore > 0.2 && validatesScore >= facilitatesScore) {
5852
+ return 'validates';
5799
5853
  }
5800
- else if (hasFacilitationPattern || hasNonImplementationLanguage ||
5801
- (facilitatesScore > 0.4 && facilitatesScore > governanceScore * 1.2)) {
5802
- // Prioritize facilitation when:
5803
- // 1. Clear facilitation language patterns detected, OR
5804
- // 2. Explicit non-implementation language (tool doesn't directly implement), OR
5805
- // 3. Facilitates score is substantial AND significantly higher than governance
5806
- primaryCapability = 'facilitates';
5854
+ else {
5855
+ return 'facilitates';
5807
5856
  }
5808
- else if (partialCapability) {
5809
- primaryCapability = 'partial';
5857
+ }
5858
+ getImplementationIndicators(safeguardId) {
5859
+ // Return specific indicators for what constitutes direct implementation for each safeguard
5860
+ const implementationMap = {
5861
+ "1.1": ['inventory', 'discovery', 'asset management', 'catalog', 'enumerate', 'scan devices', 'device database'],
5862
+ "1.2": ['unauthorized', 'rogue', 'detect', 'identify unauthorized', 'quarantine', 'block unauthorized'],
5863
+ "5.1": ['account inventory', 'user management', 'identity management', 'account lifecycle', 'user provisioning'],
5864
+ "6.3": ['multi-factor', 'mfa', '2fa', 'authentication', 'two-factor', 'multi-factor authentication'],
5865
+ "7.1": ['vulnerability', 'vuln', 'scanning', 'vulnerability management', 'security testing', 'penetration testing']
5866
+ };
5867
+ return implementationMap[safeguardId] || [];
5868
+ }
5869
+ assessCapabilityQuality(text, safeguard, claimedCapability) {
5870
+ // Assess how well the tool executes the claimed capability type
5871
+ const evidence = [];
5872
+ const gaps = [];
5873
+ // Quality assessment based on capability type
5874
+ let qualityScore = 0;
5875
+ switch (claimedCapability) {
5876
+ case 'full':
5877
+ case 'partial':
5878
+ qualityScore = this.assessImplementationQuality(text, safeguard, evidence, gaps);
5879
+ break;
5880
+ case 'governance':
5881
+ qualityScore = this.assessGovernanceQuality(text, safeguard, evidence, gaps);
5882
+ break;
5883
+ case 'facilitates':
5884
+ qualityScore = this.assessFacilitationQuality(text, safeguard, evidence, gaps);
5885
+ break;
5886
+ case 'validates':
5887
+ qualityScore = this.assessValidationQuality(text, safeguard, evidence, gaps);
5888
+ break;
5810
5889
  }
5811
- else if (governanceCapability && (facilitatesCapability || validatesCapability)) {
5812
- // Tools that primarily manage governance but also facilitate/validate
5813
- primaryCapability = 'governance';
5890
+ // Convert score to quality rating
5891
+ let quality;
5892
+ if (qualityScore >= 0.8)
5893
+ quality = 'excellent';
5894
+ else if (qualityScore >= 0.6)
5895
+ quality = 'good';
5896
+ else if (qualityScore >= 0.4)
5897
+ quality = 'fair';
5898
+ else
5899
+ quality = 'poor';
5900
+ return {
5901
+ quality,
5902
+ confidence: Math.round(qualityScore * 100),
5903
+ evidence: evidence.slice(0, 5), // Top 5 pieces of evidence
5904
+ gaps: gaps.slice(0, 3) // Top 3 gaps identified
5905
+ };
5906
+ }
5907
+ assessImplementationQuality(text, safeguard, evidence, gaps) {
5908
+ // Assess quality of direct implementation capability
5909
+ const implementationIndicators = this.getImplementationIndicators(safeguard.id);
5910
+ let score = 0;
5911
+ // Check for strong implementation language
5912
+ const strongIndicators = implementationIndicators.filter(indicator => text.includes(indicator.toLowerCase()));
5913
+ if (strongIndicators.length > 0) {
5914
+ score += 0.4;
5915
+ evidence.push(`Strong implementation indicators: ${strongIndicators.join(', ')}`);
5814
5916
  }
5815
- else if (governanceScore > facilitatesScore && governanceCapability) {
5816
- // Pure governance tools
5817
- primaryCapability = 'governance';
5917
+ // Check for comprehensive functionality description
5918
+ if (text.includes('comprehensive') || text.includes('complete') || text.includes('full')) {
5919
+ score += 0.2;
5920
+ evidence.push('Claims comprehensive functionality');
5818
5921
  }
5819
- else if (validatesScore > facilitatesScore && validatesCapability) {
5820
- // Validation-focused tools
5821
- primaryCapability = 'validates';
5922
+ // Check for automated vs manual implementation
5923
+ if (text.includes('automat') || text.includes('real-time') || text.includes('continuous')) {
5924
+ score += 0.2;
5925
+ evidence.push('Automated implementation capability');
5822
5926
  }
5823
- else if (facilitatesCapability) {
5824
- // Default facilitation
5825
- primaryCapability = 'facilitates';
5927
+ // Identify potential gaps
5928
+ if (strongIndicators.length === 0) {
5929
+ gaps.push('No clear implementation indicators found');
5826
5930
  }
5827
- // Extract evidence
5828
- const evidence = this.extractEnhancedEvidence(responseText, safeguard);
5829
- // Calculate confidence based on evidence strength and keyword matches
5830
- const keywordConfidence = (governanceScore + facilitatesScore + validatesScore) / 3;
5831
- const totalCoreAndSubElements = safeguard.coreRequirements.length + safeguard.subTaxonomicalElements.length;
5832
- const coveredCoreAndSubElements = coreCoverage.coveredElements.length + subElementCoverage.coveredElements.length;
5833
- const coverageConfidence = totalCoreAndSubElements > 0 ?
5834
- coveredCoreAndSubElements / totalCoreAndSubElements : 0;
5835
- const confidence = Math.min((keywordConfidence * 0.4 + coverageConfidence * 0.6) * 100, 100);
5931
+ return Math.min(score, 1.0);
5932
+ }
5933
+ assessGovernanceQuality(text, safeguard, evidence, gaps) {
5934
+ const governanceIndicators = ['policy', 'process', 'governance', 'compliance', 'documentation', 'oversight'];
5935
+ let score = 0;
5936
+ const foundIndicators = governanceIndicators.filter(indicator => text.includes(indicator));
5937
+ if (foundIndicators.length >= 3) {
5938
+ score += 0.5;
5939
+ evidence.push(`Strong governance capability: ${foundIndicators.join(', ')}`);
5940
+ }
5941
+ if (text.includes('documented') && text.includes('process')) {
5942
+ score += 0.3;
5943
+ evidence.push('Documented process management');
5944
+ }
5945
+ return Math.min(score, 1.0);
5946
+ }
5947
+ assessFacilitationQuality(text, safeguard, evidence, gaps) {
5948
+ const facilitationIndicators = ['enhance', 'enable', 'support', 'facilitate', 'improve', 'optimize'];
5949
+ let score = 0;
5950
+ const foundIndicators = facilitationIndicators.filter(indicator => text.includes(indicator));
5951
+ if (foundIndicators.length >= 2) {
5952
+ score += 0.4;
5953
+ evidence.push(`Clear facilitation capability: ${foundIndicators.join(', ')}`);
5954
+ }
5955
+ return Math.min(score, 1.0);
5956
+ }
5957
+ assessValidationQuality(text, safeguard, evidence, gaps) {
5958
+ const validationIndicators = ['audit', 'report', 'monitor', 'track', 'verify', 'validate'];
5959
+ let score = 0;
5960
+ const foundIndicators = validationIndicators.filter(indicator => text.includes(indicator));
5961
+ if (foundIndicators.length >= 2) {
5962
+ score += 0.4;
5963
+ evidence.push(`Strong validation capability: ${foundIndicators.join(', ')}`);
5964
+ }
5965
+ return Math.min(score, 1.0);
5966
+ }
5967
+ generateCapabilityAnalysis(vendorName, safeguard, responseText, claimedCapability, qualityAssessment) {
5968
+ // Generate the new capability-focused analysis result
5836
5969
  return {
5837
5970
  vendor: vendorName,
5838
5971
  safeguardId: safeguard.id,
5839
5972
  safeguardTitle: safeguard.title,
5840
- capability: primaryCapability,
5973
+ capability: claimedCapability,
5841
5974
  capabilities: {
5842
- full: fullCapability,
5843
- partial: partialCapability,
5844
- facilitates: facilitatesCapability,
5845
- governance: governanceCapability,
5846
- validates: validatesCapability
5847
- },
5848
- confidence: Math.round(confidence),
5849
- reasoning: this.generateCapabilityReasoning(primaryCapability, fullCapability, partialCapability, governanceCapability, facilitatesCapability, validatesCapability, coreCoverage, subElementCoverage, safeguard, hasFacilitationPattern, hasNonImplementationLanguage),
5850
- evidence,
5851
- elementsCovered: {
5852
- coreRequirements: coreCoverage.coveredElements,
5853
- subTaxonomicalElements: subElementCoverage.coveredElements,
5854
- governanceElements: governanceCoverage.coveredElements,
5855
- implementationMethods: implementationCoverage.coveredElements
5975
+ full: claimedCapability === 'full',
5976
+ partial: claimedCapability === 'partial',
5977
+ facilitates: claimedCapability === 'facilitates',
5978
+ governance: claimedCapability === 'governance',
5979
+ validates: claimedCapability === 'validates'
5856
5980
  },
5857
- elementsNotCovered: {
5858
- coreRequirements: coreCoverage.uncoveredElements,
5859
- subTaxonomicalElements: subElementCoverage.uncoveredElements
5860
- }
5981
+ confidence: qualityAssessment.confidence,
5982
+ reasoning: this.generateCapabilityReasoning(claimedCapability, qualityAssessment, safeguard),
5983
+ evidence: qualityAssessment.evidence,
5984
+ // Note: elementsCovered is now less relevant in capability-focused analysis
5985
+ // We focus on tool capability rather than element coverage
5986
+ toolCapabilityDescription: this.generateToolCapabilityDescription(claimedCapability, qualityAssessment),
5987
+ recommendedUse: this.generateRecommendedUse(claimedCapability, safeguard)
5861
5988
  };
5862
5989
  }
5990
+ generateCapabilityReasoning(claimedCapability, qualityAssessment, safeguard) {
5991
+ const capabilityDescriptions = {
5992
+ full: "directly implements the core functionality of this safeguard",
5993
+ partial: "implements limited aspects of this safeguard with clear scope boundaries",
5994
+ facilitates: "enhances or enables the implementation of this safeguard by others",
5995
+ governance: "provides governance, policy, and oversight capabilities for this safeguard",
5996
+ validates: "provides evidence, audit, and compliance validation for this safeguard"
5997
+ };
5998
+ const qualityDescriptor = qualityAssessment.quality;
5999
+ const description = capabilityDescriptions[claimedCapability];
6000
+ return `This tool ${description} with ${qualityDescriptor} capability quality. ${qualityAssessment.evidence.length > 0 ? 'Evidence: ' + qualityAssessment.evidence.join('; ') : ''}`;
6001
+ }
6002
+ generateToolCapabilityDescription(claimedCapability, qualityAssessment) {
6003
+ const roleDescriptions = {
6004
+ full: "Core Implementation Tool - Directly performs the safeguard functionality",
6005
+ partial: "Focused Implementation Tool - Performs specific aspects of the safeguard",
6006
+ facilitates: "Enablement Tool - Helps organizations implement the safeguard more effectively",
6007
+ governance: "Governance Tool - Manages policies, processes, and oversight for the safeguard",
6008
+ validates: "Compliance Tool - Provides audit, evidence, and validation capabilities"
6009
+ };
6010
+ return roleDescriptions[claimedCapability] || "Support Tool";
6011
+ }
6012
+ generateRecommendedUse(claimedCapability, safeguard) {
6013
+ const recommendations = {
6014
+ full: `Use as primary implementation tool for ${safeguard.title}. Ensure proper configuration and integration.`,
6015
+ partial: `Use as part of a multi-tool strategy for ${safeguard.title}. Supplement with additional capabilities as needed.`,
6016
+ facilitates: `Use to enhance existing safeguard implementation. Combine with direct implementation tools.`,
6017
+ governance: `Use for policy management and governance oversight. Pair with implementation and validation tools.`,
6018
+ validates: `Use for compliance monitoring and evidence collection. Combine with implementation tools for complete coverage.`
6019
+ };
6020
+ return recommendations[claimedCapability] || "Evaluate specific use case alignment.";
6021
+ }
5863
6022
  calculateKeywordScore(text, keywords) {
5864
- let score = 0;
5865
- let matches = 0;
6023
+ let matchedKeywords = 0;
6024
+ let totalMatches = 0;
5866
6025
  keywords.forEach(keyword => {
5867
6026
  const regex = new RegExp(keyword.replace(/\s+/g, '\\s+'), 'gi');
5868
6027
  const keywordMatches = (text.match(regex) || []).length;
5869
6028
  if (keywordMatches > 0) {
5870
- matches++;
5871
- score += keywordMatches;
6029
+ matchedKeywords++;
6030
+ totalMatches += keywordMatches;
5872
6031
  }
5873
6032
  });
5874
- return matches > 0 ? score / text.split(' ').length : 0;
6033
+ // Return percentage of keywords that were found, with bonus for multiple matches
6034
+ const baseScore = matchedKeywords / keywords.length;
6035
+ const matchBonus = Math.min(totalMatches * 0.1, 0.5); // Up to 50% bonus for multiple matches
6036
+ return Math.min(baseScore + matchBonus, 1.0);
5875
6037
  }
5876
6038
  analyzeElementCoverage(text, elements) {
5877
6039
  const coveredElements = [];
@@ -5981,63 +6143,6 @@ export class GRCAnalysisServer {
5981
6143
  }
5982
6144
  return reasons.join('. ');
5983
6145
  }
5984
- generateCapabilityReasoning(primaryCapability, full, partial, governance, facilitates, validates, coreCoverage, subElementCoverage, safeguard, hasFacilitationPattern = false, hasNonImplementationLanguage = false) {
5985
- const reasons = [];
5986
- // Primary capability explanation
5987
- switch (primaryCapability) {
5988
- case 'full':
5989
- reasons.push(`Provides FULL coverage of ${safeguard.title} - directly implements all core and sub-taxonomical elements`);
5990
- break;
5991
- case 'partial':
5992
- reasons.push(`Provides PARTIAL coverage of ${safeguard.title} - directly implements some but not all core and sub-taxonomical elements`);
5993
- break;
5994
- case 'facilitates':
5995
- if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
5996
- reasons.push(`FACILITATES ${safeguard.title} by creating governance frameworks, policy infrastructure, and compliance processes that enable organizations to implement the control effectively`);
5997
- }
5998
- else {
5999
- reasons.push(`FACILITATES ${safeguard.title} through data integration, automation, or technical capabilities that support implementation`);
6000
- }
6001
- break;
6002
- case 'governance':
6003
- reasons.push(`Provides GOVERNANCE capabilities for ${safeguard.title} through centralized policy management, process controls, and compliance oversight`);
6004
- break;
6005
- case 'validates':
6006
- reasons.push(`VALIDATES ${safeguard.title} implementation through evidence collection, compliance reporting, and audit capabilities`);
6007
- break;
6008
- default:
6009
- reasons.push(`No clear capability identified for ${safeguard.title}`);
6010
- }
6011
- // Coverage details
6012
- if (coreCoverage.coveredElements.length > 0) {
6013
- reasons.push(`Core elements addressed: ${coreCoverage.coveredElements.length}/${safeguard.coreRequirements.length}`);
6014
- }
6015
- if (subElementCoverage.coveredElements.length > 0) {
6016
- reasons.push(`Sub-taxonomical elements addressed: ${subElementCoverage.coveredElements.length}/${safeguard.subTaxonomicalElements.length}`);
6017
- }
6018
- // Additional context for facilitation tools
6019
- if (primaryCapability === 'facilitates') {
6020
- if (hasFacilitationPattern || hasNonImplementationLanguage || governance) {
6021
- reasons.push(`Note: This type of facilitation tool works alongside technical implementation solutions (asset scanners, MDM tools, etc.) to provide comprehensive control coverage`);
6022
- }
6023
- if (hasNonImplementationLanguage) {
6024
- reasons.push(`Tool explicitly enables compliance through governance/process rather than direct technical implementation`);
6025
- }
6026
- }
6027
- // Multi-capability products
6028
- const capabilityFlags = [governance, facilitates, validates].filter(Boolean);
6029
- if (capabilityFlags.length > 1) {
6030
- const capabilities = [];
6031
- if (governance)
6032
- capabilities.push('governance');
6033
- if (facilitates)
6034
- capabilities.push('facilitates');
6035
- if (validates)
6036
- capabilities.push('validates');
6037
- reasons.push(`Multi-capability product with: ${capabilities.join(', ')}`);
6038
- }
6039
- return reasons.join('. ');
6040
- }
6041
6146
  validateClaim(claim, analysis, capabilities, safeguard) {
6042
6147
  const validation = {
6043
6148
  coverageClaimValid: false,
@@ -6050,16 +6155,14 @@ export class GRCAnalysisServer {
6050
6155
  const meetsFullCriteria = analysis.capabilities.full;
6051
6156
  validation.coverageClaimValid = meetsFullCriteria;
6052
6157
  if (!meetsFullCriteria) {
6053
- const totalElements = safeguard.coreRequirements.length + safeguard.subTaxonomicalElements.length;
6054
- const coveredElements = analysis.elementsCovered.coreRequirements.length + analysis.elementsCovered.subTaxonomicalElements.length;
6055
- validation.gaps.push(`FULL coverage claim not supported: Only ${coveredElements}/${totalElements} core and sub-taxonomical elements covered`);
6158
+ validation.gaps.push(`FULL implementation capability claim not supported: Tool does not demonstrate direct implementation of core safeguard functionality`);
6056
6159
  }
6057
6160
  }
6058
6161
  else if (claim === 'PARTIAL') {
6059
6162
  const meetsPartialCriteria = analysis.capabilities.partial || analysis.capabilities.full;
6060
6163
  validation.coverageClaimValid = meetsPartialCriteria;
6061
6164
  if (!meetsPartialCriteria) {
6062
- validation.gaps.push(`PARTIAL coverage claim questionable: No core or sub-taxonomical elements clearly addressed`);
6165
+ validation.gaps.push(`PARTIAL implementation capability claim questionable: No core or sub-taxonomical elements clearly addressed`);
6063
6166
  }
6064
6167
  }
6065
6168
  // Validate capability claims
@@ -6103,12 +6206,18 @@ export class GRCAnalysisServer {
6103
6206
  }
6104
6207
  else {
6105
6208
  validation.recommendations.push(`Consider requesting additional information about: ${validation.gaps.join(', ')}`);
6106
- // Specific recommendations based on gaps
6107
- if (analysis.elementsNotCovered.coreRequirements.length > 0) {
6108
- validation.recommendations.push(`Request details on how these core elements are addressed: ${analysis.elementsNotCovered.coreRequirements.slice(0, 3).join(', ')}${analysis.elementsNotCovered.coreRequirements.length > 3 ? '...' : ''}`);
6209
+ // Capability-based recommendations
6210
+ if (analysis.capability === 'facilitates') {
6211
+ validation.recommendations.push('Consider pairing with direct implementation tools for complete safeguard coverage');
6212
+ }
6213
+ else if (analysis.capability === 'partial') {
6214
+ validation.recommendations.push('Evaluate scope limitations and identify complementary tools for full coverage');
6109
6215
  }
6110
- if (analysis.elementsNotCovered.subTaxonomicalElements.length > 0) {
6111
- validation.recommendations.push(`Ask for specifics on these sub-taxonomical elements: ${analysis.elementsNotCovered.subTaxonomicalElements.slice(0, 3).join(', ')}${analysis.elementsNotCovered.subTaxonomicalElements.length > 3 ? '...' : ''}`);
6216
+ else if (analysis.capability === 'governance') {
6217
+ validation.recommendations.push('Combine with technical implementation tools for complete safeguard execution');
6218
+ }
6219
+ else if (analysis.capability === 'validates') {
6220
+ validation.recommendations.push('Pair with implementation tools to ensure both execution and validation coverage');
6112
6221
  }
6113
6222
  if (!analysis.capabilities.validates && capabilities.includes('Validates')) {
6114
6223
  validation.recommendations.push(`Request examples of audit trails, reporting capabilities, and compliance evidence`);
@@ -6118,10 +6227,11 @@ export class GRCAnalysisServer {
6118
6227
  }
6119
6228
  async validateVendorMapping(args) {
6120
6229
  const { vendor_name = 'Unknown Vendor', safeguard_id, claimed_capability, supporting_text } = args;
6230
+ // Input validation
6231
+ this.validateSafeguardId(safeguard_id);
6232
+ this.validateTextInput(supporting_text, 'Supporting text');
6233
+ this.validateCapability(claimed_capability);
6121
6234
  const safeguard = CIS_SAFEGUARDS[safeguard_id];
6122
- if (!safeguard) {
6123
- throw new Error(`Safeguard ${safeguard_id} not found. Available safeguards: ${Object.keys(CIS_SAFEGUARDS).join(', ')}`);
6124
- }
6125
6235
  const validation = this.validateCapabilityClaim(vendor_name, safeguard, claimed_capability, supporting_text);
6126
6236
  return {
6127
6237
  content: [
@@ -6134,20 +6244,27 @@ export class GRCAnalysisServer {
6134
6244
  }
6135
6245
  validateCapabilityClaim(vendorName, safeguard, claimedCapability, supportingText) {
6136
6246
  const text = supportingText.toLowerCase();
6137
- // Perform actual analysis of the supporting text
6138
- const actualAnalysis = this.performEnhancedSafeguardAnalysis(vendorName, safeguard, supportingText);
6139
- // Calculate coverage percentages
6140
- const coreCoverage = this.analyzeBinaryElementCoverage(text, safeguard.coreRequirements);
6141
- const subElementCoverage = this.analyzeBinaryElementCoverage(text, safeguard.subTaxonomicalElements);
6142
- const governanceCoverage = this.analyzeBinaryElementCoverage(text, safeguard.governanceElements);
6143
- const corePercentage = safeguard.coreRequirements.length > 0 ?
6144
- (coreCoverage.coveredElements.length / safeguard.coreRequirements.length) * 100 : 0;
6145
- const subElementPercentage = safeguard.subTaxonomicalElements.length > 0 ?
6146
- (subElementCoverage.coveredElements.length / safeguard.subTaxonomicalElements.length) * 100 : 0;
6147
- const governancePercentage = safeguard.governanceElements.length > 0 ?
6148
- (governanceCoverage.coveredElements.length / safeguard.governanceElements.length) * 100 : 0;
6149
- // Validate claim against criteria
6150
- const validation = this.assessClaimAlignment(claimedCapability, actualAnalysis, corePercentage, subElementPercentage, governancePercentage, text);
6247
+ // Detect tool type and validate domain match
6248
+ const detectedToolType = this.detectToolType(supportingText, safeguard.id);
6249
+ const domainValidation = this.validateDomainMatch(safeguard.id, claimedCapability, detectedToolType);
6250
+ // Adjust capability if domain mismatch detected
6251
+ let effectiveCapability = claimedCapability;
6252
+ let originalClaim;
6253
+ if (domainValidation.should_adjust_capability) {
6254
+ originalClaim = claimedCapability;
6255
+ effectiveCapability = domainValidation.adjusted_capability;
6256
+ }
6257
+ // Perform capability-focused analysis of the supporting text
6258
+ const actualAnalysis = this.performCapabilityAnalysis(vendorName, safeguard, supportingText);
6259
+ // Validate claimed capability against actual capability analysis and domain requirements
6260
+ const validation = this.assessCapabilityClaimAlignment(claimedCapability, effectiveCapability, actualAnalysis, domainValidation, text);
6261
+ // Add domain validation gaps if capability was adjusted
6262
+ if (domainValidation.should_adjust_capability) {
6263
+ validation.gaps.unshift(`Domain mismatch: ${domainValidation.reasoning}`);
6264
+ validation.recommendations.unshift(`Correct capability mapping should be '${effectiveCapability.toUpperCase()}' for ${detectedToolType} tools`);
6265
+ // Reduce confidence for domain mismatches
6266
+ validation.confidence = Math.max(validation.confidence - 20, 0);
6267
+ }
6151
6268
  return {
6152
6269
  vendor: vendorName,
6153
6270
  safeguard_id: safeguard.id,
@@ -6155,11 +6272,16 @@ export class GRCAnalysisServer {
6155
6272
  claimed_capability: claimedCapability,
6156
6273
  validation_status: validation.status,
6157
6274
  confidence_score: validation.confidence,
6158
- evidence_analysis: {
6159
- core_requirements_coverage: Math.round(corePercentage),
6160
- sub_elements_coverage: Math.round(subElementPercentage),
6161
- governance_alignment: Math.round(governancePercentage),
6162
- language_consistency: validation.languageConsistency
6275
+ actual_capability_detected: actualAnalysis.capability,
6276
+ capability_confidence: actualAnalysis.confidence,
6277
+ tool_capability_description: actualAnalysis.toolCapabilityDescription,
6278
+ recommended_use: actualAnalysis.recommendedUse,
6279
+ domain_validation: {
6280
+ required_tool_type: domainValidation.required_tool_types.join('/'),
6281
+ detected_tool_type: detectedToolType,
6282
+ domain_match: domainValidation.domain_match,
6283
+ capability_adjusted: domainValidation.should_adjust_capability,
6284
+ original_claim: originalClaim
6163
6285
  },
6164
6286
  gaps_identified: validation.gaps,
6165
6287
  strengths_identified: validation.strengths,
@@ -6167,112 +6289,42 @@ export class GRCAnalysisServer {
6167
6289
  detailed_feedback: validation.feedback
6168
6290
  };
6169
6291
  }
6170
- assessClaimAlignment(claimedCapability, actualAnalysis, corePercentage, subElementPercentage, governancePercentage, text) {
6292
+ assessCapabilityClaimAlignment(claimedCapability, effectiveCapability, actualAnalysis, domainValidation, text) {
6171
6293
  const gaps = [];
6172
6294
  const strengths = [];
6173
6295
  const recommendations = [];
6174
- let languageConsistency = 0;
6296
+ // Compare claimed capability with what we actually detected
6297
+ const claimedLower = claimedCapability.toLowerCase();
6298
+ const effectiveLower = effectiveCapability.toLowerCase();
6299
+ const actualCapability = actualAnalysis.capability;
6175
6300
  let alignmentScore = 0;
6176
- switch (claimedCapability.toLowerCase()) {
6177
- case 'full':
6178
- // Validate FULL claim
6179
- if (corePercentage >= 70 && subElementPercentage >= 40) {
6180
- alignmentScore = 85;
6181
- strengths.push('High coverage of core requirements and sub-elements');
6182
- }
6183
- else if (corePercentage >= 80 && subElementPercentage >= 30) {
6184
- // Alternative path: very high core with moderate sub-elements
6185
- alignmentScore = 80;
6186
- strengths.push('Very high core requirements coverage with adequate sub-element coverage');
6187
- }
6188
- else {
6189
- alignmentScore = Math.max(0, (corePercentage + subElementPercentage) / 2 - 15);
6190
- if (corePercentage < 70)
6191
- gaps.push(`Core requirements coverage (${Math.round(corePercentage)}%) below FULL threshold (70%)`);
6192
- if (subElementPercentage < 40)
6193
- gaps.push(`Sub-element coverage (${Math.round(subElementPercentage)}%) below FULL threshold (40%)`);
6194
- }
6195
- // Check for conflicting facilitation language
6196
- if (this.hasFacilitationLanguage(text)) {
6197
- alignmentScore -= 30;
6198
- gaps.push('Contains facilitation language inconsistent with FULL implementation claim');
6199
- }
6200
- languageConsistency = this.assessImplementationLanguage(text);
6201
- break;
6202
- case 'partial':
6203
- // Validate PARTIAL claim
6204
- if (corePercentage >= 30 || (corePercentage > 0 && subElementPercentage >= 20)) {
6205
- alignmentScore = 75;
6206
- strengths.push('Appropriate coverage level for PARTIAL implementation');
6207
- }
6208
- else {
6209
- alignmentScore = Math.max(0, corePercentage + subElementPercentage - 10);
6210
- gaps.push(`Coverage too low even for PARTIAL claim: ${Math.round(corePercentage)}% core, ${Math.round(subElementPercentage)}% sub-elements`);
6211
- }
6212
- // Check for scope boundary definition
6213
- if (this.hasScopeBoundaries(text)) {
6214
- strengths.push('Clearly defines scope boundaries and limitations');
6215
- alignmentScore += 10;
6216
- }
6217
- else {
6218
- gaps.push('Should clearly define scope boundaries for PARTIAL implementation');
6219
- recommendations.push('Specify exactly which elements are covered and which are not');
6220
- }
6221
- languageConsistency = this.assessImplementationLanguage(text);
6222
- break;
6223
- case 'facilitates':
6224
- // Validate FACILITATES claim
6225
- if (this.hasFacilitationLanguage(text) || actualAnalysis.capabilities.facilitates) {
6226
- alignmentScore = 80;
6227
- strengths.push('Contains appropriate facilitation and enablement language');
6228
- }
6229
- else {
6230
- alignmentScore = 40;
6231
- gaps.push('Lacks clear facilitation language (enables, supports, provides framework)');
6232
- }
6233
- // Check that it doesn't claim direct implementation
6234
- if (this.hasDirectImplementationLanguage(text)) {
6235
- // Special handling: If it lacks facilitation language AND claims implementation, stay QUESTIONABLE
6236
- if (alignmentScore <= 40) {
6237
- alignmentScore = 45; // Keep it in QUESTIONABLE range
6238
- }
6239
- else {
6240
- alignmentScore -= 15;
6241
- }
6242
- gaps.push('Claims direct implementation, inconsistent with FACILITATES capability');
6243
- }
6244
- languageConsistency = this.assessFacilitationLanguage(text);
6245
- break;
6246
- case 'governance':
6247
- // Validate GOVERNANCE claim
6248
- if (governancePercentage >= 60 || actualAnalysis.capabilities.governance) {
6249
- alignmentScore = 85;
6250
- strengths.push('Strong governance element coverage and policy management language');
6251
- }
6252
- else {
6253
- alignmentScore = Math.max(30, governancePercentage);
6254
- gaps.push(`Governance element coverage (${Math.round(governancePercentage)}%) below expected threshold (60%)`);
6255
- }
6256
- languageConsistency = this.assessGovernanceLanguage(text);
6257
- break;
6258
- case 'validates':
6259
- // Validate VALIDATES claim
6260
- if (actualAnalysis.capabilities.validates) {
6261
- alignmentScore = 85;
6262
- strengths.push('Contains evidence collection and reporting capabilities');
6263
- }
6264
- else {
6265
- alignmentScore = 30;
6266
- gaps.push('Lacks validation language (audit, report, evidence, verify, monitor)');
6267
- }
6268
- languageConsistency = this.assessValidationLanguage(text);
6269
- break;
6270
- default:
6271
- alignmentScore = 0;
6272
- gaps.push(`Unknown capability type: ${claimedCapability}`);
6273
- languageConsistency = 0;
6301
+ // Check if claim aligns with actual analysis
6302
+ if (claimedLower === actualCapability) {
6303
+ alignmentScore = actualAnalysis.confidence;
6304
+ strengths.push(`Claimed capability '${claimedCapability}' aligns with detected capability`);
6305
+ strengths.push(`Tool demonstrates appropriate ${actualAnalysis.toolCapabilityDescription.toLowerCase()}`);
6306
+ }
6307
+ else if (effectiveLower === actualCapability) {
6308
+ // Domain validation adjusted the capability and it matches the analysis
6309
+ alignmentScore = Math.max(actualAnalysis.confidence - 20, 30);
6310
+ gaps.push(`Original claim '${claimedCapability}' doesn't match tool type, adjusted to '${effectiveCapability}'`);
6311
+ strengths.push(`Adjusted capability '${effectiveCapability}' aligns with tool analysis`);
6312
+ }
6313
+ else {
6314
+ // Neither claimed nor effective capability matches the analysis
6315
+ alignmentScore = Math.max(actualAnalysis.confidence - 40, 10);
6316
+ gaps.push(`Claimed capability '${claimedCapability}' doesn't align with detected capability '${actualCapability}'`);
6317
+ gaps.push(`Tool appears to be: ${actualAnalysis.toolCapabilityDescription}`);
6318
+ }
6319
+ // Add evidence from the capability analysis
6320
+ if (actualAnalysis.evidence && actualAnalysis.evidence.length > 0) {
6321
+ strengths.push(`Supporting evidence: ${actualAnalysis.evidence.slice(0, 2).join('; ')}`);
6274
6322
  }
6275
- // Determine overall status
6323
+ // Domain validation feedback
6324
+ if (!domainValidation.domain_match) {
6325
+ gaps.push(`Tool type '${domainValidation.detected_tool_type}' not appropriate for this safeguard domain`);
6326
+ }
6327
+ // Determine overall status based on alignment score
6276
6328
  let status;
6277
6329
  if (alignmentScore >= 70) {
6278
6330
  status = 'SUPPORTED';
@@ -6283,18 +6335,18 @@ export class GRCAnalysisServer {
6283
6335
  else {
6284
6336
  status = 'UNSUPPORTED';
6285
6337
  }
6286
- // Generate recommendations
6287
- if (gaps.length > 0) {
6288
- recommendations.push('Address identified gaps to strengthen capability claim');
6289
- }
6338
+ // Generate capability-focused recommendations
6339
+ recommendations.push(actualAnalysis.recommendedUse);
6290
6340
  if (status === 'QUESTIONABLE') {
6291
- recommendations.push('Provide additional evidence or clarify scope to support claim');
6341
+ recommendations.push('Consider clarifying tool capabilities or adjusting capability claim');
6342
+ }
6343
+ if (!domainValidation.domain_match) {
6344
+ 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`);
6292
6345
  }
6293
- const feedback = this.generateValidationFeedback(claimedCapability, status, gaps, strengths, alignmentScore);
6346
+ const feedback = this.generateCapabilityValidationFeedback(claimedCapability, effectiveCapability, actualCapability, status, alignmentScore, domainValidation);
6294
6347
  return {
6295
6348
  status,
6296
6349
  confidence: Math.round(alignmentScore),
6297
- languageConsistency: Math.round(languageConsistency),
6298
6350
  gaps,
6299
6351
  strengths,
6300
6352
  recommendations,
@@ -6352,8 +6404,195 @@ export class GRCAnalysisServer {
6352
6404
  ];
6353
6405
  return this.calculateKeywordScore(text, validationKeywords) * 100;
6354
6406
  }
6407
+ detectToolType(text, safeguardId) {
6408
+ const lowerText = text.toLowerCase();
6409
+ // Enhanced keyword definitions with scoring weights and context
6410
+ const toolTypePatterns = {
6411
+ 'inventory': {
6412
+ primary: [
6413
+ 'asset management', 'inventory management', 'cmdb', 'configuration management database',
6414
+ 'asset discovery', 'hardware inventory', 'software inventory', 'device inventory',
6415
+ 'asset tracking', 'it asset management', 'endpoint discovery', 'asset lifecycle'
6416
+ ],
6417
+ secondary: [
6418
+ 'inventory', 'discovery', 'device management', 'endpoint management',
6419
+ 'configuration management', 'asset database', 'equipment tracking'
6420
+ ],
6421
+ weight: { primary: 3, secondary: 1 }
6422
+ },
6423
+ 'identity_management': {
6424
+ primary: [
6425
+ 'identity management', 'iam', 'active directory', 'identity provider',
6426
+ 'single sign-on', 'sso', 'multi-factor authentication', 'mfa',
6427
+ 'user management', 'account management', 'directory service'
6428
+ ],
6429
+ secondary: [
6430
+ 'ldap', 'authentication', 'access management', 'identity access management',
6431
+ 'user directory', 'account lifecycle', 'privileged access'
6432
+ ],
6433
+ weight: { primary: 3, secondary: 1 }
6434
+ },
6435
+ 'vulnerability_management': {
6436
+ primary: [
6437
+ 'vulnerability management', 'vulnerability scanner', 'patch management',
6438
+ 'security scanning', 'vulnerability assessment', 'penetration testing'
6439
+ ],
6440
+ secondary: [
6441
+ 'vuln scan', 'security scanner', 'network scanner', 'scanning capabilities',
6442
+ 'security assessment', 'vulnerability scanning', 'patch deployment'
6443
+ ],
6444
+ weight: { primary: 3, secondary: 1 }
6445
+ },
6446
+ 'threat_intelligence': {
6447
+ primary: [
6448
+ 'threat intelligence', 'cyber threat intelligence', 'threat intel',
6449
+ 'threat feed', 'ioc feed', 'security intelligence', 'threat data'
6450
+ ],
6451
+ secondary: [
6452
+ 'enrichment', 'data feed', 'contextual data', 'risk intelligence',
6453
+ 'threat indicators', 'intelligence platform', 'threat correlation'
6454
+ ],
6455
+ weight: { primary: 3, secondary: 1 }
6456
+ },
6457
+ 'network_security': {
6458
+ primary: [
6459
+ 'firewall', 'network access control', 'nac', 'intrusion detection',
6460
+ 'network security', 'network segmentation'
6461
+ ],
6462
+ secondary: [
6463
+ 'network monitoring', 'traffic analysis', 'perimeter security',
6464
+ 'network protection', 'network filtering'
6465
+ ],
6466
+ weight: { primary: 3, secondary: 1 }
6467
+ },
6468
+ 'governance': {
6469
+ primary: [
6470
+ 'grc', 'governance risk compliance', 'compliance management',
6471
+ 'policy management', 'risk management', 'audit management'
6472
+ ],
6473
+ secondary: [
6474
+ 'governance', 'compliance platform', 'policy enforcement',
6475
+ 'regulatory compliance', 'framework management'
6476
+ ],
6477
+ weight: { primary: 3, secondary: 1 }
6478
+ },
6479
+ 'security_analytics': {
6480
+ primary: [
6481
+ 'siem', 'security information event management', 'security analytics',
6482
+ 'soar', 'security orchestration', 'log management'
6483
+ ],
6484
+ secondary: [
6485
+ 'security monitoring', 'event correlation', 'log analysis',
6486
+ 'security intelligence', 'incident response platform'
6487
+ ],
6488
+ weight: { primary: 3, secondary: 1 }
6489
+ }
6490
+ };
6491
+ // Calculate scores for each tool type
6492
+ const toolScores = {};
6493
+ for (const [toolType, patterns] of Object.entries(toolTypePatterns)) {
6494
+ let score = 0;
6495
+ // Check primary keywords
6496
+ for (const keyword of patterns.primary) {
6497
+ if (lowerText.includes(keyword)) {
6498
+ score += patterns.weight.primary;
6499
+ }
6500
+ }
6501
+ // Check secondary keywords
6502
+ for (const keyword of patterns.secondary) {
6503
+ if (lowerText.includes(keyword)) {
6504
+ score += patterns.weight.secondary;
6505
+ }
6506
+ }
6507
+ toolScores[toolType] = score;
6508
+ }
6509
+ // Apply safeguard-specific context weighting if provided
6510
+ if (safeguardId && toolScores) {
6511
+ const contextBonus = 1; // Small bonus for domain alignment
6512
+ // Asset inventory safeguards (1.1, 1.2) favor inventory tools
6513
+ if (['1.1', '1.2'].includes(safeguardId) && toolScores['inventory'] > 0) {
6514
+ toolScores['inventory'] += contextBonus;
6515
+ }
6516
+ // Account inventory safeguards (5.1, 5.2, 5.3) favor identity tools
6517
+ if (['5.1', '5.2', '5.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
6518
+ toolScores['identity_management'] += contextBonus;
6519
+ }
6520
+ // Authentication safeguards (6.1, 6.2, 6.3) favor identity tools
6521
+ if (['6.1', '6.2', '6.3'].includes(safeguardId) && toolScores['identity_management'] > 0) {
6522
+ toolScores['identity_management'] += contextBonus;
6523
+ }
6524
+ // Vulnerability safeguards (7.1-7.7) favor vulnerability management tools
6525
+ if (['7.1', '7.2', '7.3', '7.4', '7.5', '7.6', '7.7'].includes(safeguardId) && toolScores['vulnerability_management'] > 0) {
6526
+ toolScores['vulnerability_management'] += contextBonus;
6527
+ }
6528
+ }
6529
+ // Find the tool type with highest score
6530
+ let maxScore = 0;
6531
+ let detectedType = 'unknown';
6532
+ for (const [toolType, score] of Object.entries(toolScores)) {
6533
+ if (score > maxScore) {
6534
+ maxScore = score;
6535
+ detectedType = toolType;
6536
+ }
6537
+ }
6538
+ // Require minimum score threshold to avoid false positives
6539
+ return maxScore >= 2 ? detectedType : 'unknown';
6540
+ }
6541
+ validateDomainMatch(safeguardId, claimedCapability, detectedToolType) {
6542
+ const domainReq = SAFEGUARD_DOMAIN_REQUIREMENTS[safeguardId];
6543
+ if (!domainReq) {
6544
+ return {
6545
+ domain_match: true,
6546
+ required_tool_types: [],
6547
+ should_adjust_capability: false,
6548
+ reasoning: 'No domain restrictions defined for this safeguard'
6549
+ };
6550
+ }
6551
+ const isFullOrPartial = ['full', 'partial'].includes(claimedCapability.toLowerCase());
6552
+ const toolTypeMatches = domainReq.required_tool_types.includes(detectedToolType);
6553
+ if (isFullOrPartial && !toolTypeMatches) {
6554
+ return {
6555
+ domain_match: false,
6556
+ required_tool_types: domainReq.required_tool_types,
6557
+ should_adjust_capability: true,
6558
+ adjusted_capability: 'facilitates',
6559
+ 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.`
6560
+ };
6561
+ }
6562
+ return {
6563
+ domain_match: true,
6564
+ required_tool_types: domainReq.required_tool_types,
6565
+ should_adjust_capability: false,
6566
+ reasoning: toolTypeMatches ?
6567
+ `Tool type '${detectedToolType}' is appropriate for ${domainReq.domain} safeguard` :
6568
+ 'No domain validation required for this capability type'
6569
+ };
6570
+ }
6571
+ generateCapabilityValidationFeedback(claimedCapability, effectiveCapability, actualCapability, status, score, domainValidation) {
6572
+ let feedback = `Capability Validation: ${claimedCapability.toUpperCase()} claim is ${status} (${Math.round(score)}% confidence)\n\n`;
6573
+ // Analysis summary
6574
+ feedback += `ANALYSIS:\n`;
6575
+ feedback += `• Claimed: ${claimedCapability.toUpperCase()}\n`;
6576
+ if (effectiveCapability !== claimedCapability) {
6577
+ feedback += `• Domain Adjusted: ${effectiveCapability.toUpperCase()} (${domainValidation.reasoning})\n`;
6578
+ }
6579
+ feedback += `• Detected: ${actualCapability.toUpperCase()}\n`;
6580
+ feedback += `• Tool Type: ${domainValidation.detected_tool_type}\n\n`;
6581
+ // Assessment
6582
+ feedback += `ASSESSMENT: `;
6583
+ if (claimedCapability.toLowerCase() === actualCapability) {
6584
+ feedback += 'Claimed capability aligns perfectly with tool analysis.';
6585
+ }
6586
+ else if (effectiveCapability.toLowerCase() === actualCapability) {
6587
+ feedback += 'After domain validation adjustment, capability aligns with tool analysis.';
6588
+ }
6589
+ else {
6590
+ feedback += `Capability mismatch detected. Tool functions as ${actualCapability.toUpperCase()} rather than claimed ${claimedCapability.toUpperCase()}.`;
6591
+ }
6592
+ return feedback;
6593
+ }
6355
6594
  generateValidationFeedback(claimedCapability, status, gaps, strengths, score) {
6356
- let feedback = `Validation of ${claimedCapability.toUpperCase()} capability claim: ${status} (${Math.round(score)}% alignment)\n\n`;
6595
+ let feedback = `Validation of ${claimedCapability.toUpperCase()} capability role claim: ${status} (${Math.round(score)}% alignment)\n\n`;
6357
6596
  if (strengths.length > 0) {
6358
6597
  feedback += `STRENGTHS:\n${strengths.map(s => `• ${s}`).join('\n')}\n\n`;
6359
6598
  }
@@ -6363,21 +6602,122 @@ export class GRCAnalysisServer {
6363
6602
  feedback += `ASSESSMENT: `;
6364
6603
  switch (status) {
6365
6604
  case 'SUPPORTED':
6366
- feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability.';
6605
+ feedback += 'The vendor\'s supporting evidence strongly aligns with their claimed capability role.';
6367
6606
  break;
6368
6607
  case 'QUESTIONABLE':
6369
6608
  feedback += 'The vendor\'s evidence partially supports their claim but has notable gaps or inconsistencies.';
6370
6609
  break;
6371
6610
  case 'UNSUPPORTED':
6372
- feedback += 'The vendor\'s evidence does not adequately support their claimed capability.';
6611
+ feedback += 'The vendor\'s evidence does not adequately support their claimed capability role.';
6373
6612
  break;
6374
6613
  }
6375
6614
  return feedback;
6376
6615
  }
6616
+ // Enhanced error handling and formatting
6617
+ formatErrorMessage(error, toolName) {
6618
+ if (error instanceof Error) {
6619
+ // Production-friendly error messages
6620
+ switch (error.message) {
6621
+ case /^Safeguard .+ not found/.test(error.message) ? error.message : '':
6622
+ return `❌ Invalid safeguard ID. Use 'list_available_safeguards' to see available CIS Control safeguards.`;
6623
+ case /^Unknown tool/.test(error.message) ? error.message : '':
6624
+ return `❌ Tool '${toolName}' is not available. Available tools: analyze_vendor_response, validate_vendor_mapping, validate_coverage_claim, get_safeguard_details, list_available_safeguards.`;
6625
+ default:
6626
+ return `❌ Error in ${toolName}: ${error.message}`;
6627
+ }
6628
+ }
6629
+ return `❌ Unexpected error in ${toolName}: ${String(error)}`;
6630
+ }
6631
+ getCachedSafeguardDetails(safeguardId, includeExamples) {
6632
+ const cacheKey = `${safeguardId}_${includeExamples}`;
6633
+ const cached = this.cache.safeguardDetails.get(cacheKey);
6634
+ if (cached && (Date.now() - cached.timestamp < 5 * 60 * 1000)) { // 5 minute cache
6635
+ return cached.data;
6636
+ }
6637
+ return null;
6638
+ }
6639
+ setCachedSafeguardDetails(safeguardId, includeExamples, data) {
6640
+ const cacheKey = `${safeguardId}_${includeExamples}`;
6641
+ this.cache.safeguardDetails.set(cacheKey, {
6642
+ data,
6643
+ timestamp: Date.now()
6644
+ });
6645
+ // Periodic cache cleanup to prevent memory leaks
6646
+ if (Date.now() - this.cache.lastCacheCleanup > 10 * 60 * 1000) { // 10 minutes
6647
+ this.cleanupCache();
6648
+ }
6649
+ }
6650
+ cleanupCache() {
6651
+ const now = Date.now();
6652
+ const maxAge = 10 * 60 * 1000; // 10 minutes
6653
+ // Clean up safeguard details cache
6654
+ for (const [key, value] of this.cache.safeguardDetails.entries()) {
6655
+ if (now - value.timestamp > maxAge) {
6656
+ this.cache.safeguardDetails.delete(key);
6657
+ }
6658
+ }
6659
+ this.cache.lastCacheCleanup = now;
6660
+ }
6661
+ recordToolExecution(toolName, executionTime) {
6662
+ this.performanceMetrics.totalRequests++;
6663
+ if (!this.performanceMetrics.toolExecutionTimes.has(toolName)) {
6664
+ this.performanceMetrics.toolExecutionTimes.set(toolName, []);
6665
+ }
6666
+ const times = this.performanceMetrics.toolExecutionTimes.get(toolName);
6667
+ times.push(executionTime);
6668
+ // Keep only last 100 measurements for memory efficiency
6669
+ if (times.length > 100) {
6670
+ times.shift();
6671
+ }
6672
+ }
6673
+ getPerformanceStats() {
6674
+ const uptime = Date.now() - this.performanceMetrics.startTime;
6675
+ const avgTimes = Array.from(this.performanceMetrics.toolExecutionTimes.entries())
6676
+ .map(([tool, times]) => {
6677
+ const avg = times.reduce((a, b) => a + b, 0) / times.length;
6678
+ return `${tool}: ${avg.toFixed(2)}ms`;
6679
+ });
6680
+ return `Performance Stats (Uptime: ${(uptime / 1000).toFixed(1)}s, Requests: ${this.performanceMetrics.totalRequests}, Errors: ${this.performanceMetrics.errorCount})\n${avgTimes.join(', ')}`;
6681
+ }
6682
+ // Input validation and sanitization
6683
+ validateSafeguardId(safeguardId) {
6684
+ if (!safeguardId || typeof safeguardId !== 'string') {
6685
+ throw new Error('Safeguard ID is required and must be a string');
6686
+ }
6687
+ if (!/^[0-9]+\.[0-9]+$/.test(safeguardId)) {
6688
+ throw new Error('Safeguard ID must be in format "X.Y" (e.g., "1.1", "5.1")');
6689
+ }
6690
+ if (!CIS_SAFEGUARDS[safeguardId]) {
6691
+ throw new Error(`Safeguard ${safeguardId} not found`);
6692
+ }
6693
+ }
6694
+ validateTextInput(text, fieldName) {
6695
+ if (!text || typeof text !== 'string') {
6696
+ throw new Error(`${fieldName} is required and must be a string`);
6697
+ }
6698
+ if (text.length > 10000) {
6699
+ throw new Error(`${fieldName} must be less than 10,000 characters`);
6700
+ }
6701
+ if (text.trim().length < 10) {
6702
+ throw new Error(`${fieldName} must contain at least 10 meaningful characters`);
6703
+ }
6704
+ }
6705
+ validateCapability(capability) {
6706
+ const validCapabilities = ['full', 'partial', 'facilitates', 'governance', 'validates'];
6707
+ if (!validCapabilities.includes(capability.toLowerCase())) {
6708
+ throw new Error(`Invalid capability. Must be one of: ${validCapabilities.join(', ')}`);
6709
+ }
6710
+ }
6377
6711
  async run() {
6378
6712
  const transport = new StdioServerTransport();
6379
6713
  await this.server.connect(transport);
6380
6714
  console.error('FrameworkMCP server running on stdio');
6715
+ // Log performance stats every 5 minutes in production
6716
+ if (process.env.NODE_ENV === 'production') {
6717
+ setInterval(() => {
6718
+ console.error(`[FrameworkMCP] ${this.getPerformanceStats()}`);
6719
+ }, 5 * 60 * 1000);
6720
+ }
6381
6721
  }
6382
6722
  }
6383
6723
  const server = new GRCAnalysisServer();