Skip to main content
Glama

IIA-MCP Server

by rp4
compliance.ts11.5 kB
import { VercelRequest, VercelResponse } from '@vercel/node'; import * as fs from 'fs/promises'; import * as path from 'path'; interface ComplianceResult { scenario: string; relevantStandards: string[]; complianceAssessment: { standard: string; title: string; assessment: string; complianceLevel: 'compliant' | 'partial' | 'non-compliant' | 'insufficient-info'; recommendations: string[]; }[]; overallAssessment: string; keyRecommendations: string[]; } async function validateCompliance( scenario: string, standardsToCheck?: string[] ): Promise<ComplianceResult> { let relevantStandards = standardsToCheck || []; if (relevantStandards.length === 0) { // Auto-detect relevant standards based on scenario keywords relevantStandards = detectRelevantStandards(scenario); } const complianceAssessment = []; const keyRecommendations: string[] = []; for (const standardNumber of relevantStandards) { const assessment = await assessAgainstStandard(scenario, standardNumber); if (assessment) { complianceAssessment.push(assessment); keyRecommendations.push(...assessment.recommendations); } } const overallAssessment = generateOverallAssessment(complianceAssessment); return { scenario, relevantStandards, complianceAssessment, overallAssessment, keyRecommendations: [...new Set(keyRecommendations)].slice(0, 5) // Dedupe and limit }; } function detectRelevantStandards(scenario: string): string[] { const keywords = scenario.toLowerCase(); const relevantStandards: string[] = []; // Independence and objectivity if (keywords.includes('independence') || keywords.includes('objective') || keywords.includes('conflict')) { relevantStandards.push('1100', '1110', '1120', '1130'); } // Planning if (keywords.includes('plan') || keywords.includes('planning') || keywords.includes('strategy')) { relevantStandards.push('2010', '2020', '2030'); } // Risk management if (keywords.includes('risk') || keywords.includes('assessment')) { relevantStandards.push('2010', '2120', '2200'); } // Governance if (keywords.includes('governance') || keywords.includes('board') || keywords.includes('oversight')) { relevantStandards.push('2110', '2060'); } // Control if (keywords.includes('control') || keywords.includes('testing') || keywords.includes('evaluation')) { relevantStandards.push('2130', '2300', '2320'); } // Engagement planning if (keywords.includes('engagement') || keywords.includes('audit plan') || keywords.includes('scope')) { relevantStandards.push('2200', '2210', '2220', '2230'); } // Communication and reporting if (keywords.includes('report') || keywords.includes('communication') || keywords.includes('finding')) { relevantStandards.push('2400', '2410', '2420', '2440'); } // Performance and quality if (keywords.includes('quality') || keywords.includes('performance') || keywords.includes('supervision')) { relevantStandards.push('2340', '2500'); } return [...new Set(relevantStandards)]; // Remove duplicates } async function assessAgainstStandard(scenario: string, standardNumber: string) { try { const standardDetails = await getStandardContent(standardNumber); if (!standardDetails) { return null; } const assessment = analyzeCompliance(scenario, standardDetails); return { standard: standardNumber, title: standardDetails.title, assessment: assessment.description, complianceLevel: assessment.level, recommendations: assessment.recommendations }; } catch (error) { console.error(`Error assessing standard ${standardNumber}:`, error); return null; } } async function getStandardContent(standardNumber: string) { const REPO_PATH = './iia-resources'; const series = standardNumber.startsWith('1') ? '1000-series' : '2000-series'; const standardsPath = path.join(REPO_PATH, 'standards', series); try { const files = await fs.readdir(standardsPath); const matchingFile = files.find(file => file.includes(standardNumber) && file.endsWith('.md') ); if (!matchingFile) { return null; } const filePath = path.join(standardsPath, matchingFile); const content = await fs.readFile(filePath, 'utf-8'); // Parse title from metadata or content const titleMatch = content.match(/title:\s*"([^"]+)"/); const title = titleMatch ? titleMatch[1] : `Standard ${standardNumber}`; return { title, content }; } catch (error) { console.error(`Error getting standard content for ${standardNumber}:`, error); return null; } } function analyzeCompliance(scenario: string, standardDetails: { title: string; content: string }) { const scenarioLower = scenario.toLowerCase(); const contentLower = standardDetails.content.toLowerCase(); // Simple compliance analysis based on keyword matching and pattern recognition const requirements = extractRequirements(standardDetails.content); const recommendations: string[] = []; let complianceScore = 0; let totalRequirements = requirements.length; for (const requirement of requirements) { const matches = checkRequirementCompliance(scenarioLower, requirement.toLowerCase()); if (matches.isCompliant) { complianceScore++; } else { recommendations.push(matches.recommendation); } } // Determine compliance level let level: 'compliant' | 'partial' | 'non-compliant' | 'insufficient-info'; const complianceRatio = totalRequirements > 0 ? complianceScore / totalRequirements : 0; if (complianceRatio >= 0.8) { level = 'compliant'; } else if (complianceRatio >= 0.5) { level = 'partial'; } else if (complianceRatio > 0) { level = 'non-compliant'; } else { level = 'insufficient-info'; } const description = generateComplianceDescription(level, complianceScore, totalRequirements); return { level, description, recommendations: recommendations.slice(0, 3) // Limit recommendations }; } function extractRequirements(content: string): string[] { const requirements: string[] = []; // Look for "must" statements const mustMatches = content.match(/[^.]*must[^.]*\./gi); if (mustMatches) { requirements.push(...mustMatches); } // Look for "should" statements const shouldMatches = content.match(/[^.]*should[^.]*\./gi); if (shouldMatches) { requirements.push(...shouldMatches.slice(0, 2)); // Limit should statements } return requirements.map(req => req.trim()).filter(req => req.length > 20); } function checkRequirementCompliance(scenario: string, requirement: string) { // Simple keyword-based compliance checking const requirementKeywords = extractKeywords(requirement); const scenarioKeywords = extractKeywords(scenario); const matchingKeywords = requirementKeywords.filter(keyword => scenarioKeywords.some(scenarioKeyword => scenarioKeyword.includes(keyword) || keyword.includes(scenarioKeyword) ) ); const matchRatio = matchingKeywords.length / Math.max(requirementKeywords.length, 1); if (matchRatio >= 0.3) { return { isCompliant: true, recommendation: '' }; } else { return { isCompliant: false, recommendation: generateRecommendation(requirement) }; } } function extractKeywords(text: string): string[] { const words = text.toLowerCase() .replace(/[^\w\s]/g, ' ') .split(/\s+/) .filter(word => word.length > 3 && !isStopWord(word)); return [...new Set(words)]; } function isStopWord(word: string): boolean { const stopWords = new Set([ 'must', 'should', 'will', 'that', 'this', 'with', 'from', 'they', 'have', 'been', 'their', 'would', 'there', 'could', 'other', 'such', 'when', 'where', 'what', 'which', 'than', 'more', 'also', 'some', 'time' ]); return stopWords.has(word); } function generateRecommendation(requirement: string): string { // Extract key action words and generate recommendations if (requirement.includes('must establish')) { return 'Establish required processes, policies, or procedures as specified'; } else if (requirement.includes('must report')) { return 'Implement proper reporting mechanisms and communication channels'; } else if (requirement.includes('must assess') || requirement.includes('must evaluate')) { return 'Conduct thorough assessment and evaluation processes'; } else if (requirement.includes('independence') || requirement.includes('objective')) { return 'Review and strengthen independence and objectivity safeguards'; } else { return 'Review compliance with this requirement and implement necessary controls'; } } function generateComplianceDescription( level: string, score: number, total: number ): string { switch (level) { case 'compliant': return `Scenario appears to align well with standard requirements (${score}/${total} requirements addressed)`; case 'partial': return `Scenario partially complies with standard requirements (${score}/${total} requirements addressed). Some gaps identified`; case 'non-compliant': return `Scenario has significant gaps in compliance with standard requirements (${score}/${total} requirements addressed)`; case 'insufficient-info': return 'Insufficient information in scenario to assess compliance with this standard'; default: return 'Unable to assess compliance'; } } function generateOverallAssessment(assessments: any[]): string { if (assessments.length === 0) { return 'No relevant standards identified for assessment'; } const compliantCount = assessments.filter(a => a.complianceLevel === 'compliant').length; const partialCount = assessments.filter(a => a.complianceLevel === 'partial').length; const nonCompliantCount = assessments.filter(a => a.complianceLevel === 'non-compliant').length; if (compliantCount === assessments.length) { return 'Scenario demonstrates good compliance with relevant IIA standards'; } else if (compliantCount > assessments.length / 2) { return 'Scenario shows mostly compliant practices with some areas for improvement'; } else if (partialCount > nonCompliantCount) { return 'Scenario shows partial compliance with standards - several improvements needed'; } else { return 'Scenario indicates significant compliance gaps requiring attention'; } } export default async function handler(req: VercelRequest, res: VercelResponse) { // Set CORS headers res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); if (req.method === 'OPTIONS') { return res.status(200).end(); } if (req.method === 'POST') { try { const { scenario, standards } = req.body; if (!scenario || typeof scenario !== 'string') { return res.status(400).json({ error: 'Scenario is required' }); } const result = await validateCompliance(scenario, standards); return res.json(result); } catch (error) { console.error('Error validating compliance:', error); return res.status(500).json({ error: 'Compliance validation failed' }); } } return res.status(405).json({ error: 'Method not allowed' }); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rp4/IIA-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server