framework-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts ADDED
@@ -0,0 +1,841 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
+ import {
6
+ CallToolRequestSchema,
7
+ ListToolsRequestSchema,
8
+ Tool,
9
+ } from '@modelcontextprotocol/sdk/types.js';
10
+ import * as fs from 'fs/promises';
11
+ import * as path from 'path';
12
+
13
+ interface SafeguardElement {
14
+ id: string;
15
+ title: string;
16
+ description: string;
17
+ implementationGroup: 'IG1' | 'IG2' | 'IG3';
18
+ assetType: string[];
19
+ securityFunction: string[];
20
+ // Color-coded elements from the CIS visualizations
21
+ governanceElements: string[]; // Orange - MUST be met
22
+ coreRequirements: string[]; // Green - The "what" of the safeguard
23
+ subTaxonomicalElements: string[]; // Yellow - Sub-taxonomical elements
24
+ implementationSuggestions: string[]; // Gray - Suggestions for implementation
25
+ relatedSafeguards: string[];
26
+ keywords: string[];
27
+ }
28
+
29
+ interface VendorAnalysis {
30
+ vendor: string;
31
+ safeguardId: string;
32
+ safeguardTitle: string;
33
+ governance: boolean;
34
+ facilitates: boolean;
35
+ coverage: 'full' | 'partial' | 'none';
36
+ validates: boolean;
37
+ confidence: number;
38
+ reasoning: string;
39
+ evidence: string[];
40
+ // Enhanced coverage analysis
41
+ governanceElementsCovered: string[];
42
+ coreRequirementsCovered: string[];
43
+ subElementsCovered: string[];
44
+ implementationMethodsUsed: string[];
45
+ coverageBreakdown: {
46
+ governance: number; // % of orange elements covered
47
+ core: number; // % of green elements covered
48
+ subElements: number; // % of yellow elements covered
49
+ overall: number; // Overall percentage
50
+ };
51
+ }
52
+
53
+ interface AnalysisResult {
54
+ summary: {
55
+ totalVendors: number;
56
+ safeguardId: string;
57
+ safeguardTitle: string;
58
+ byAttribute: {
59
+ governance: number;
60
+ facilitates: number;
61
+ validates: number;
62
+ fullCoverage: number;
63
+ partialCoverage: number;
64
+ };
65
+ averageCoverageBreakdown: {
66
+ governance: number;
67
+ core: number;
68
+ subElements: number;
69
+ overall: number;
70
+ };
71
+ };
72
+ vendors: VendorAnalysis[];
73
+ recommendations: string[];
74
+ }
75
+
76
+ // Enhanced CIS Controls Framework Data with color-coded categorization
77
+ const CIS_SAFEGUARDS: Record<string, SafeguardElement> = {
78
+ "1.1": {
79
+ id: "1.1",
80
+ title: "Establish and Maintain a Detailed Enterprise Asset Inventory",
81
+ description: "Establish and maintain an accurate, detailed, and up-to-date inventory of all enterprise assets with the potential to store or process data",
82
+ implementationGroup: "IG1",
83
+ assetType: ["end-user devices", "network devices", "IoT devices", "servers"],
84
+ securityFunction: ["Identify"],
85
+ governanceElements: [ // Orange - MUST be met
86
+ "establish inventory process",
87
+ "maintain inventory process",
88
+ "documented process",
89
+ "review and update bi-annually",
90
+ "enterprise asset management policy"
91
+ ],
92
+ coreRequirements: [ // Green - The "what"
93
+ "accurate inventory",
94
+ "detailed inventory",
95
+ "up-to-date inventory",
96
+ "all enterprise assets",
97
+ "potential to store or process data"
98
+ ],
99
+ subTaxonomicalElements: [ // Yellow - Sub-taxonomical elements
100
+ "network address (if static)",
101
+ "hardware address",
102
+ "machine name",
103
+ "enterprise asset owner",
104
+ "department for each asset",
105
+ "approved to connect to network",
106
+ "end-user devices (portable and mobile)",
107
+ "network devices",
108
+ "non-computing/IoT devices",
109
+ "servers",
110
+ "physical connection",
111
+ "virtual connection",
112
+ "remote connection",
113
+ "cloud environments",
114
+ "regularly connected devices not under enterprise control"
115
+ ],
116
+ implementationSuggestions: [ // Gray - Implementation suggestions
117
+ "MDM type tools for mobile devices",
118
+ "enterprise and software asset management tool",
119
+ "asset discovery tools",
120
+ "DHCP logging",
121
+ "passive discovery tools"
122
+ ],
123
+ relatedSafeguards: ["1.2", "1.3", "1.4", "1.5", "2.1", "3.2", "4.1", "5.1"],
124
+ keywords: ["asset", "inventory", "device", "network", "mobile", "IoT", "server", "detailed", "accurate", "up-to-date"]
125
+ },
126
+ "5.1": {
127
+ id: "5.1",
128
+ title: "Establish and Maintain an Inventory of Accounts",
129
+ description: "Establish and maintain an inventory of all accounts managed in the enterprise",
130
+ implementationGroup: "IG1",
131
+ assetType: ["users"],
132
+ securityFunction: ["Identify"],
133
+ governanceElements: [ // Orange - MUST be met
134
+ "establish inventory process",
135
+ "maintain inventory process",
136
+ "validate all active accounts are authorized",
137
+ "recurring schedule minimum quarterly",
138
+ "account management policy"
139
+ ],
140
+ coreRequirements: [ // Green - The "what"
141
+ "inventory of all accounts",
142
+ "user accounts",
143
+ "administrator accounts",
144
+ "managed in the enterprise"
145
+ ],
146
+ subTaxonomicalElements: [ // Yellow - Sub-taxonomical elements
147
+ "person's name",
148
+ "username",
149
+ "start/stop dates",
150
+ "department",
151
+ "account status",
152
+ "account type",
153
+ "access rights",
154
+ "last login date"
155
+ ],
156
+ implementationSuggestions: [ // Gray - Implementation suggestions
157
+ "identity and access management tool",
158
+ "directory services",
159
+ "automated account provisioning",
160
+ "account lifecycle management",
161
+ "role-based access control system"
162
+ ],
163
+ relatedSafeguards: ["1.1", "2.1", "5.2", "5.3", "5.4", "5.5", "5.6", "6.1", "6.2"],
164
+ keywords: ["accounts", "inventory", "user", "administrator", "name", "username", "dates", "department", "quarterly"]
165
+ },
166
+ "6.3": {
167
+ id: "6.3",
168
+ title: "Require MFA for Externally-Exposed Applications",
169
+ description: "Require all externally-exposed enterprise or third-party applications to enforce MFA",
170
+ implementationGroup: "IG1",
171
+ assetType: ["users"],
172
+ securityFunction: ["Protect"],
173
+ governanceElements: [ // Orange - MUST be met
174
+ "require MFA enforcement",
175
+ "policy for externally-exposed applications",
176
+ "MFA compliance verification"
177
+ ],
178
+ coreRequirements: [ // Green - The "what"
179
+ "multi-factor authentication",
180
+ "all externally-exposed applications",
181
+ "enterprise applications",
182
+ "third-party applications",
183
+ "enforce MFA where supported"
184
+ ],
185
+ subTaxonomicalElements: [ // Yellow - Sub-taxonomical elements
186
+ "authentication factors",
187
+ "something you know (password)",
188
+ "something you have (token)",
189
+ "something you are (biometric)",
190
+ "external access points",
191
+ "application inventory",
192
+ "exposure assessment"
193
+ ],
194
+ implementationSuggestions: [ // Gray - Implementation suggestions
195
+ "directory service enforcement",
196
+ "SSO provider enforcement",
197
+ "multi-factor authentication tools",
198
+ "SAML integration",
199
+ "OAuth implementation",
200
+ "conditional access policies"
201
+ ],
202
+ relatedSafeguards: ["2.1", "4.1", "5.1", "6.1", "6.2"],
203
+ keywords: ["MFA", "multi-factor", "authentication", "externally-exposed", "applications", "third-party", "SSO", "directory"]
204
+ },
205
+ "7.1": {
206
+ id: "7.1",
207
+ title: "Establish and Maintain a Vulnerability Management Process",
208
+ description: "Establish and maintain a documented vulnerability management process for enterprise assets",
209
+ implementationGroup: "IG1",
210
+ assetType: ["documentation"],
211
+ securityFunction: ["Govern"],
212
+ governanceElements: [ // Orange - MUST be met
213
+ "establish documented process",
214
+ "maintain vulnerability management process",
215
+ "review and update documentation annually",
216
+ "update when significant enterprise changes occur",
217
+ "vulnerability management policy"
218
+ ],
219
+ coreRequirements: [ // Green - The "what"
220
+ "vulnerability management process",
221
+ "enterprise assets scope",
222
+ "documented procedures",
223
+ "vulnerability identification",
224
+ "vulnerability assessment"
225
+ ],
226
+ subTaxonomicalElements: [ // Yellow - Sub-taxonomical elements
227
+ "vulnerability scanning procedures",
228
+ "risk assessment criteria",
229
+ "remediation prioritization",
230
+ "patch management integration",
231
+ "vulnerability tracking",
232
+ "reporting requirements",
233
+ "roles and responsibilities",
234
+ "escalation procedures"
235
+ ],
236
+ implementationSuggestions: [ // Gray - Implementation suggestions
237
+ "vulnerability scanning tools",
238
+ "patch management systems",
239
+ "vulnerability databases",
240
+ "CVSS scoring",
241
+ "automated scanning",
242
+ "vulnerability management platforms"
243
+ ],
244
+ relatedSafeguards: ["1.1", "2.1", "7.2", "7.3", "7.4", "7.5", "7.6", "7.7"],
245
+ keywords: ["vulnerability", "management", "process", "documented", "annual", "review", "enterprise", "assets"]
246
+ },
247
+ "1.2": {
248
+ id: "1.2",
249
+ title: "Address Unauthorized Assets",
250
+ description: "Ensure that a process exists to address unauthorized assets on a weekly basis",
251
+ implementationGroup: "IG1",
252
+ assetType: ["devices"],
253
+ securityFunction: ["Respond"],
254
+ governanceElements: [ // Orange - MUST be met
255
+ "ensure process exists",
256
+ "weekly basis requirement",
257
+ "unauthorized asset handling policy"
258
+ ],
259
+ coreRequirements: [ // Green - The "what"
260
+ "address unauthorized assets",
261
+ "process to handle unauthorized devices",
262
+ "weekly execution"
263
+ ],
264
+ subTaxonomicalElements: [ // Yellow - Sub-taxonomical elements
265
+ "unauthorized asset detection",
266
+ "asset classification",
267
+ "response timeline",
268
+ "documentation requirements"
269
+ ],
270
+ implementationSuggestions: [ // Gray - Implementation suggestions
271
+ "remove asset from network",
272
+ "deny asset from connecting remotely",
273
+ "quarantine asset",
274
+ "automated response systems",
275
+ "network access control"
276
+ ],
277
+ relatedSafeguards: ["1.1", "1.3"],
278
+ keywords: ["unauthorized", "assets", "weekly", "remove", "deny", "quarantine", "process"]
279
+ }
280
+ };
281
+
282
+ class GRCAnalysisServer {
283
+ private server: Server;
284
+
285
+ constructor() {
286
+ this.server = new Server(
287
+ {
288
+ name: 'framework-mcp',
289
+ version: '1.0.0',
290
+ }
291
+ );
292
+
293
+ this.setupToolHandlers();
294
+ }
295
+
296
+ private setupToolHandlers() {
297
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
298
+ tools: [
299
+ {
300
+ name: 'analyze_vendor_response',
301
+ description: 'Analyze a vendor response for a specific CIS Control safeguard against the 4 GRC attributes with detailed sub-element coverage',
302
+ inputSchema: {
303
+ type: 'object',
304
+ properties: {
305
+ vendor_name: {
306
+ type: 'string',
307
+ description: 'Name of the vendor'
308
+ },
309
+ safeguard_id: {
310
+ type: 'string',
311
+ description: 'CIS Control safeguard ID (e.g., "5.1", "1.1", "6.3")',
312
+ pattern: '^[0-9]+\\.[0-9]+$'
313
+ },
314
+ response_text: {
315
+ type: 'string',
316
+ description: 'Vendor response text to analyze'
317
+ }
318
+ },
319
+ required: ['vendor_name', 'safeguard_id', 'response_text']
320
+ }
321
+ } as Tool,
322
+ {
323
+ name: 'get_safeguard_details',
324
+ description: 'Get detailed information about a CIS Control safeguard including governance requirements, core elements, and sub-taxonomical breakdown',
325
+ inputSchema: {
326
+ type: 'object',
327
+ properties: {
328
+ safeguard_id: {
329
+ type: 'string',
330
+ description: 'CIS Control safeguard ID (e.g., "5.1", "1.1")',
331
+ pattern: '^[0-9]+\\.[0-9]+$'
332
+ },
333
+ include_examples: {
334
+ type: 'boolean',
335
+ description: 'Include implementation examples and suggestions',
336
+ default: true
337
+ }
338
+ },
339
+ required: ['safeguard_id']
340
+ }
341
+ } as Tool,
342
+ {
343
+ name: 'validate_coverage_claim',
344
+ description: 'Validate a vendor\'s coverage claim (FULL/PARTIAL) against specific safeguard requirements',
345
+ inputSchema: {
346
+ type: 'object',
347
+ properties: {
348
+ vendor_name: {
349
+ type: 'string',
350
+ description: 'Name of the vendor'
351
+ },
352
+ safeguard_id: {
353
+ type: 'string',
354
+ description: 'CIS Control safeguard ID',
355
+ pattern: '^[0-9]+\\.[0-9]+$'
356
+ },
357
+ coverage_claim: {
358
+ type: 'string',
359
+ enum: ['FULL', 'PARTIAL'],
360
+ description: 'Vendor\'s coverage claim'
361
+ },
362
+ response_text: {
363
+ type: 'string',
364
+ description: 'Vendor response explaining their coverage'
365
+ },
366
+ capabilities: {
367
+ type: 'array',
368
+ items: { type: 'string' },
369
+ description: 'List of vendor capabilities/attributes (Governance, Facilitates, Validates)'
370
+ }
371
+ },
372
+ required: ['vendor_name', 'safeguard_id', 'coverage_claim', 'response_text', 'capabilities']
373
+ }
374
+ } as Tool,
375
+ {
376
+ name: 'list_available_safeguards',
377
+ description: 'List all available CIS Control safeguards with their categorization',
378
+ inputSchema: {
379
+ type: 'object',
380
+ properties: {
381
+ implementation_group: {
382
+ type: 'string',
383
+ enum: ['IG1', 'IG2', 'IG3'],
384
+ description: 'Filter by implementation group (optional)'
385
+ },
386
+ security_function: {
387
+ type: 'string',
388
+ enum: ['Identify', 'Protect', 'Detect', 'Respond', 'Recover', 'Govern'],
389
+ description: 'Filter by security function (optional)'
390
+ }
391
+ }
392
+ }
393
+ } as Tool
394
+ ],
395
+ }));
396
+
397
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
398
+ const { name, arguments: args } = request.params;
399
+
400
+ try {
401
+ switch (name) {
402
+ case 'analyze_vendor_response':
403
+ return await this.analyzeVendorResponse(args);
404
+ case 'get_safeguard_details':
405
+ return await this.getSafeguardDetails(args);
406
+ case 'validate_coverage_claim':
407
+ return await this.validateCoverageClaim(args);
408
+ case 'list_available_safeguards':
409
+ return await this.listAvailableSafeguards(args);
410
+ default:
411
+ throw new Error(`Unknown tool: ${name}`);
412
+ }
413
+ } catch (error) {
414
+ return {
415
+ content: [
416
+ {
417
+ type: 'text',
418
+ text: `Error: ${error instanceof Error ? error.message : String(error)}`,
419
+ },
420
+ ],
421
+ };
422
+ }
423
+ });
424
+ }
425
+
426
+ private async getSafeguardDetails(args: any) {
427
+ const { safeguard_id, include_examples = true } = args;
428
+
429
+ const safeguard = CIS_SAFEGUARDS[safeguard_id];
430
+ if (!safeguard) {
431
+ throw new Error(`Safeguard ${safeguard_id} not found. Use list_available_safeguards to see available safeguards.`);
432
+ }
433
+
434
+ const result = {
435
+ ...safeguard,
436
+ elementBreakdown: {
437
+ governanceElements: {
438
+ count: safeguard.governanceElements.length,
439
+ description: "Orange elements - MUST be met for compliance",
440
+ elements: safeguard.governanceElements
441
+ },
442
+ coreRequirements: {
443
+ count: safeguard.coreRequirements.length,
444
+ description: "Green elements - The 'what' of the safeguard",
445
+ elements: safeguard.coreRequirements
446
+ },
447
+ subTaxonomicalElements: {
448
+ count: safeguard.subTaxonomicalElements.length,
449
+ description: "Yellow elements - Detailed sub-taxonomical components",
450
+ elements: safeguard.subTaxonomicalElements
451
+ },
452
+ ...(include_examples && {
453
+ implementationSuggestions: {
454
+ count: safeguard.implementationSuggestions.length,
455
+ description: "Gray elements - Implementation suggestions and methods",
456
+ elements: safeguard.implementationSuggestions
457
+ }
458
+ })
459
+ }
460
+ };
461
+
462
+ return {
463
+ content: [
464
+ {
465
+ type: 'text',
466
+ text: JSON.stringify(result, null, 2),
467
+ },
468
+ ],
469
+ };
470
+ }
471
+
472
+ private async listAvailableSafeguards(args: any) {
473
+ const { implementation_group, security_function } = args;
474
+
475
+ let safeguards = Object.values(CIS_SAFEGUARDS);
476
+
477
+ if (implementation_group) {
478
+ safeguards = safeguards.filter(s => s.implementationGroup === implementation_group);
479
+ }
480
+
481
+ if (security_function) {
482
+ safeguards = safeguards.filter(s => s.securityFunction.includes(security_function));
483
+ }
484
+
485
+ const summary = {
486
+ totalSafeguards: safeguards.length,
487
+ byImplementationGroup: {
488
+ IG1: safeguards.filter(s => s.implementationGroup === 'IG1').length,
489
+ IG2: safeguards.filter(s => s.implementationGroup === 'IG2').length,
490
+ IG3: safeguards.filter(s => s.implementationGroup === 'IG3').length,
491
+ },
492
+ safeguards: safeguards.map(s => ({
493
+ id: s.id,
494
+ title: s.title,
495
+ implementationGroup: s.implementationGroup,
496
+ assetType: s.assetType,
497
+ securityFunction: s.securityFunction
498
+ }))
499
+ };
500
+
501
+ return {
502
+ content: [
503
+ {
504
+ type: 'text',
505
+ text: JSON.stringify(summary, null, 2),
506
+ },
507
+ ],
508
+ };
509
+ }
510
+
511
+ private async analyzeVendorResponse(args: any) {
512
+ const { vendor_name, safeguard_id, response_text } = args;
513
+
514
+ const safeguard = CIS_SAFEGUARDS[safeguard_id];
515
+ if (!safeguard) {
516
+ throw new Error(`Safeguard ${safeguard_id} not found. Available safeguards: ${Object.keys(CIS_SAFEGUARDS).join(', ')}`);
517
+ }
518
+
519
+ const analysis = this.performEnhancedSafeguardAnalysis(vendor_name, safeguard, response_text);
520
+
521
+ return {
522
+ content: [
523
+ {
524
+ type: 'text',
525
+ text: JSON.stringify(analysis, null, 2),
526
+ },
527
+ ],
528
+ };
529
+ }
530
+
531
+ private async validateCoverageClaim(args: any) {
532
+ const { vendor_name, safeguard_id, coverage_claim, response_text, capabilities } = args;
533
+
534
+ const safeguard = CIS_SAFEGUARDS[safeguard_id];
535
+ if (!safeguard) {
536
+ throw new Error(`Safeguard ${safeguard_id} not found`);
537
+ }
538
+
539
+ const analysis = this.performEnhancedSafeguardAnalysis(vendor_name, safeguard, response_text);
540
+
541
+ // Validate the coverage claim
542
+ const validation = this.validateClaim(coverage_claim, analysis, capabilities, safeguard);
543
+
544
+ return {
545
+ content: [
546
+ {
547
+ type: 'text',
548
+ text: JSON.stringify({
549
+ vendor: vendor_name,
550
+ safeguardId: safeguard_id,
551
+ claimedCoverage: coverage_claim,
552
+ claimedCapabilities: capabilities,
553
+ analysis,
554
+ validation
555
+ }, null, 2),
556
+ },
557
+ ],
558
+ };
559
+ }
560
+
561
+ private performEnhancedSafeguardAnalysis(vendorName: string, safeguard: SafeguardElement, responseText: string): VendorAnalysis {
562
+ const text = responseText.toLowerCase();
563
+
564
+ // Enhanced keywords based on GRC attributes
565
+ const governanceKeywords = [
566
+ 'policy', 'policies', 'manage', 'process', 'workflow', 'governance', 'grc',
567
+ 'compliance management', 'documented', 'establish', 'maintain', 'procedure'
568
+ ];
569
+
570
+ const facilitatesKeywords = [
571
+ 'improve', 'enhance', 'optimize', 'faster', 'better', 'stronger', 'automate',
572
+ 'streamline', 'efficiency', 'facilitate', 'support', 'enable', 'accelerate'
573
+ ];
574
+
575
+ const validatesKeywords = [
576
+ 'audit', 'report', 'evidence', 'verify', 'validate', 'check', 'monitor',
577
+ 'compliance report', 'assessment', 'logging', 'tracking', 'review', 'attest'
578
+ ];
579
+
580
+ // Calculate GRC attribute scores
581
+ const governanceScore = this.calculateKeywordScore(text, governanceKeywords);
582
+ const facilitatesScore = this.calculateKeywordScore(text, facilitatesKeywords);
583
+ const validatesScore = this.calculateKeywordScore(text, validatesKeywords);
584
+
585
+ // Analyze coverage against each category of elements
586
+ const governanceCoverage = this.analyzeElementCoverage(text, safeguard.governanceElements);
587
+ const coreCoverage = this.analyzeElementCoverage(text, safeguard.coreRequirements);
588
+ const subElementCoverage = this.analyzeElementCoverage(text, safeguard.subTaxonomicalElements);
589
+ const implementationCoverage = this.analyzeElementCoverage(text, safeguard.implementationSuggestions);
590
+
591
+ // Calculate overall coverage breakdown
592
+ const coverageBreakdown = {
593
+ governance: governanceCoverage.percentage,
594
+ core: coreCoverage.percentage,
595
+ subElements: subElementCoverage.percentage,
596
+ overall: (governanceCoverage.percentage * 0.4 + coreCoverage.percentage * 0.4 + subElementCoverage.percentage * 0.2)
597
+ };
598
+
599
+ // Determine coverage level based on comprehensive analysis
600
+ let coverage: 'full' | 'partial' | 'none' = 'none';
601
+ if (coverageBreakdown.governance >= 80 && coverageBreakdown.core >= 70) {
602
+ coverage = 'full';
603
+ } else if (coverageBreakdown.overall >= 25) {
604
+ coverage = 'partial';
605
+ }
606
+
607
+ // Extract evidence with enhanced context
608
+ const evidence = this.extractEnhancedEvidence(responseText, safeguard);
609
+
610
+ // Calculate confidence based on multiple factors
611
+ const confidence = Math.min(
612
+ (
613
+ (governanceScore + facilitatesScore + validatesScore) / 3 * 0.4 +
614
+ coverageBreakdown.overall / 100 * 0.6
615
+ ) * 100,
616
+ 100
617
+ );
618
+
619
+ return {
620
+ vendor: vendorName,
621
+ safeguardId: safeguard.id,
622
+ safeguardTitle: safeguard.title,
623
+ governance: governanceScore > 0.3,
624
+ facilitates: facilitatesScore > 0.3,
625
+ coverage,
626
+ validates: validatesScore > 0.3,
627
+ confidence: Math.round(confidence),
628
+ reasoning: this.generateEnhancedReasoning(governanceScore, facilitatesScore, validatesScore, coverageBreakdown, safeguard),
629
+ evidence,
630
+ governanceElementsCovered: governanceCoverage.coveredElements,
631
+ coreRequirementsCovered: coreCoverage.coveredElements,
632
+ subElementsCovered: subElementCoverage.coveredElements,
633
+ implementationMethodsUsed: implementationCoverage.coveredElements,
634
+ coverageBreakdown: {
635
+ governance: Math.round(coverageBreakdown.governance),
636
+ core: Math.round(coverageBreakdown.core),
637
+ subElements: Math.round(coverageBreakdown.subElements),
638
+ overall: Math.round(coverageBreakdown.overall)
639
+ }
640
+ };
641
+ }
642
+
643
+ private calculateKeywordScore(text: string, keywords: string[]): number {
644
+ let score = 0;
645
+ let matches = 0;
646
+
647
+ keywords.forEach(keyword => {
648
+ const regex = new RegExp(keyword.replace(/\s+/g, '\\s+'), 'gi');
649
+ const keywordMatches = (text.match(regex) || []).length;
650
+ if (keywordMatches > 0) {
651
+ matches++;
652
+ score += keywordMatches;
653
+ }
654
+ });
655
+
656
+ return matches > 0 ? score / text.split(' ').length : 0;
657
+ }
658
+
659
+ private analyzeElementCoverage(text: string, elements: string[]): {
660
+ percentage: number;
661
+ coveredElements: string[];
662
+ uncoveredElements: string[];
663
+ } {
664
+ const coveredElements: string[] = [];
665
+ const uncoveredElements: string[] = [];
666
+
667
+ elements.forEach(element => {
668
+ const elementKeywords = element.toLowerCase().split(/[\s\-\(\)\/]+/).filter(w => w.length > 2);
669
+ let elementFound = false;
670
+
671
+ // Check for keyword matches
672
+ for (const keyword of elementKeywords) {
673
+ if (text.includes(keyword)) {
674
+ elementFound = true;
675
+ break;
676
+ }
677
+ }
678
+
679
+ // Check for semantic matches
680
+ if (!elementFound) {
681
+ const regex = new RegExp(element.replace(/[()]/g, '').replace(/\s+/g, '\\s*'), 'gi');
682
+ if (regex.test(text)) {
683
+ elementFound = true;
684
+ }
685
+ }
686
+
687
+ if (elementFound) {
688
+ coveredElements.push(element);
689
+ } else {
690
+ uncoveredElements.push(element);
691
+ }
692
+ });
693
+
694
+ return {
695
+ percentage: elements.length > 0 ? (coveredElements.length / elements.length) * 100 : 0,
696
+ coveredElements,
697
+ uncoveredElements
698
+ };
699
+ }
700
+
701
+ private extractEnhancedEvidence(text: string, safeguard: SafeguardElement): string[] {
702
+ const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 15);
703
+ const evidence: string[] = [];
704
+
705
+ // Collect all keywords from all categories
706
+ const allKeywords = [
707
+ ...safeguard.keywords,
708
+ ...safeguard.governanceElements,
709
+ ...safeguard.coreRequirements,
710
+ ...safeguard.subTaxonomicalElements
711
+ ];
712
+
713
+ // Extract relevant sentences
714
+ allKeywords.forEach(keyword => {
715
+ sentences.forEach(sentence => {
716
+ const lowerSentence = sentence.toLowerCase();
717
+ const lowerKeyword = keyword.toLowerCase();
718
+
719
+ if (lowerSentence.includes(lowerKeyword) &&
720
+ !evidence.includes(sentence.trim()) &&
721
+ evidence.length < 8) {
722
+ evidence.push(sentence.trim());
723
+ }
724
+ });
725
+ });
726
+
727
+ return evidence;
728
+ }
729
+
730
+ private generateEnhancedReasoning(
731
+ governance: number,
732
+ facilitates: number,
733
+ validates: number,
734
+ coverageBreakdown: any,
735
+ safeguard: SafeguardElement
736
+ ): string {
737
+ const reasons = [];
738
+
739
+ // GRC attribute analysis
740
+ if (governance > 0.3) reasons.push(`Strong governance capabilities for ${safeguard.title}`);
741
+ if (facilitates > 0.3) reasons.push(`Enhancement features that facilitate ${safeguard.id} implementation`);
742
+ if (validates > 0.3) reasons.push(`Validation capabilities for ${safeguard.id} compliance verification`);
743
+
744
+ // Coverage breakdown analysis
745
+ reasons.push(`Coverage breakdown: ${coverageBreakdown.governance}% governance, ${coverageBreakdown.core}% core requirements, ${coverageBreakdown.subElements}% sub-elements`);
746
+
747
+ if (coverageBreakdown.governance < 50) {
748
+ reasons.push(`Limited governance element coverage may impact compliance`);
749
+ }
750
+
751
+ if (coverageBreakdown.core < 50) {
752
+ reasons.push(`Core requirements coverage needs improvement`);
753
+ }
754
+
755
+ return reasons.join('. ');
756
+ }
757
+
758
+ private validateClaim(claim: string, analysis: VendorAnalysis, capabilities: string[], safeguard: SafeguardElement) {
759
+ const validation = {
760
+ coverageClaimValid: false,
761
+ capabilityClaimsValid: {} as Record<string, boolean>,
762
+ gaps: [] as string[],
763
+ recommendations: [] as string[]
764
+ };
765
+
766
+ // Validate coverage claim
767
+ if (claim === 'FULL') {
768
+ // For FULL claim, should cover at least 80% of governance elements and 70% of core requirements
769
+ const meetsFullCriteria = analysis.coverageBreakdown.governance >= 80 &&
770
+ analysis.coverageBreakdown.core >= 70;
771
+ validation.coverageClaimValid = meetsFullCriteria;
772
+
773
+ if (!meetsFullCriteria) {
774
+ validation.gaps.push(`FULL coverage claim not supported: Governance ${analysis.coverageBreakdown.governance}% (need 80%+), Core ${analysis.coverageBreakdown.core}% (need 70%+)`);
775
+ }
776
+ } else if (claim === 'PARTIAL') {
777
+ // For PARTIAL claim, should cover at least some elements
778
+ const meetsPartialCriteria = analysis.coverageBreakdown.overall >= 20;
779
+ validation.coverageClaimValid = meetsPartialCriteria;
780
+
781
+ if (!meetsPartialCriteria) {
782
+ validation.gaps.push(`PARTIAL coverage claim questionable: Overall coverage only ${analysis.coverageBreakdown.overall}%`);
783
+ }
784
+ }
785
+
786
+ // Validate capability claims
787
+ capabilities.forEach(capability => {
788
+ switch (capability.toLowerCase()) {
789
+ case 'governance':
790
+ validation.capabilityClaimsValid[capability] = analysis.governance;
791
+ if (!analysis.governance) {
792
+ validation.gaps.push(`Governance capability not evidenced in response`);
793
+ }
794
+ break;
795
+ case 'facilitates':
796
+ validation.capabilityClaimsValid[capability] = analysis.facilitates;
797
+ if (!analysis.facilitates) {
798
+ validation.gaps.push(`Facilitates capability not evidenced in response`);
799
+ }
800
+ break;
801
+ case 'validates':
802
+ validation.capabilityClaimsValid[capability] = analysis.validates;
803
+ if (!analysis.validates) {
804
+ validation.gaps.push(`Validates capability not evidenced in response`);
805
+ }
806
+ break;
807
+ }
808
+ });
809
+
810
+ // Generate recommendations
811
+ if (validation.gaps.length === 0) {
812
+ validation.recommendations.push(`Claims appear to be well-supported by the vendor response`);
813
+ } else {
814
+ validation.recommendations.push(`Consider requesting additional information about: ${validation.gaps.join(', ')}`);
815
+
816
+ // Specific recommendations based on gaps
817
+ if (analysis.coverageBreakdown.governance < 80) {
818
+ validation.recommendations.push(`Request details on policy management and documented processes`);
819
+ }
820
+
821
+ if (analysis.coverageBreakdown.core < 70) {
822
+ validation.recommendations.push(`Ask for specifics on how core safeguard requirements are met`);
823
+ }
824
+
825
+ if (!analysis.validates && capabilities.includes('Validates')) {
826
+ validation.recommendations.push(`Request examples of audit trails, reporting capabilities, and compliance evidence`);
827
+ }
828
+ }
829
+
830
+ return validation;
831
+ }
832
+
833
+ async run() {
834
+ const transport = new StdioServerTransport();
835
+ await this.server.connect(transport);
836
+ console.error('FrameworkMCP server running on stdio');
837
+ }
838
+ }
839
+
840
+ const server = new GRCAnalysisServer();
841
+ server.run().catch(console.error);