UNPKG

stellar-cyber-mcp-agents

Version:

Model Context Protocol (MCP) server for Stellar Cyber security operations with specialized multi-agent analysis capabilities

479 lines 18.8 kB
import { EventEmitter } from 'events'; import { AgentType } from '../types/agent.js'; export class IntelligenceSharingService extends EventEmitter { intelligenceStore = new Map(); subscriptions = new Map(); collaborationRequests = new Map(); agentCapabilities = new Map(); cleanupInterval; constructor() { super(); // Initialize agent capabilities this.initializeCapabilities(); // Start cleanup interval for expired intelligence this.cleanupInterval = setInterval(() => { this.cleanupExpiredIntelligence(); }, 60000); // Check every minute } initializeCapabilities() { this.agentCapabilities.set(AgentType.INVESTIGATION, [ 'case-analysis', 'evidence-collection', 'timeline-reconstruction' ]); this.agentCapabilities.set(AgentType.CORRELATION, [ 'pattern-matching', 'cross-case-analysis', 'similarity-scoring' ]); this.agentCapabilities.set(AgentType.NETWORK_ANALYSIS, [ 'traffic-analysis', 'connection-mapping', 'protocol-analysis' ]); this.agentCapabilities.set(AgentType.MALWARE_ANALYSIS, [ 'static-analysis', 'dynamic-analysis', 'signature-generation' ]); this.agentCapabilities.set(AgentType.CREDENTIAL_ANALYSIS, [ 'credential-validation', 'breach-checking', 'password-analysis' ]); this.agentCapabilities.set(AgentType.CAMPAIGN_DETECTION, [ 'clustering', 'ttp-analysis', 'infrastructure-mapping' ]); this.agentCapabilities.set(AgentType.WORKFLOW, [ 'orchestration', 'task-coordination', 'dependency-management' ]); } shareIntelligence(item) { // Validate intelligence item this.validateIntelligenceItem(item); // Store intelligence this.intelligenceStore.set(item.id, item); // Notify subscribers this.notifySubscribers(item); // Emit intelligence shared event this.emit('intelligence:shared', { itemId: item.id, source: item.source, type: item.type, confidence: item.confidence }); } validateIntelligenceItem(item) { if (!item.id || !item.type || !item.source || !item.data) { throw new Error('Invalid intelligence item: missing required fields'); } if (item.confidence < 0 || item.confidence > 1) { throw new Error('Invalid confidence value: must be between 0 and 1'); } } queryIntelligence(query) { const results = []; const now = Date.now(); for (const item of this.intelligenceStore.values()) { // Check if item is expired if (!query.includeExpired && item.ttl && (new Date(item.timestamp).getTime() + item.ttl) < now) { continue; } // Apply filters if (query.types && !query.types.includes(item.type)) continue; if (query.minConfidence && item.confidence < query.minConfidence) continue; if (query.sources && !query.sources.some(s => this.agentIdsEqual(s, item.source))) continue; if (query.tags && query.tags.length > 0) { const hasMatchingTag = query.tags.some(tag => item.tags.includes(tag)); if (!hasMatchingTag) continue; } if (query.timeRange) { const itemTime = new Date(item.timestamp).getTime(); const startTime = new Date(query.timeRange.start).getTime(); const endTime = new Date(query.timeRange.end).getTime(); if (itemTime < startTime || itemTime > endTime) continue; } results.push(item); } // Sort by timestamp (newest first) and confidence results.sort((a, b) => { const timeA = new Date(a.timestamp).getTime(); const timeB = new Date(b.timestamp).getTime(); if (timeB !== timeA) return timeB - timeA; return b.confidence - a.confidence; }); // Apply limit if (query.limit) { return results.slice(0, query.limit); } return results; } subscribe(agentId, query, callback) { const subscriptionId = crypto.randomUUID(); const subscription = { id: subscriptionId, agentId, query, callback, active: true, created: new Date().toISOString() }; this.subscriptions.set(subscriptionId, subscription); // Send initial results const initialResults = this.queryIntelligence(query); if (initialResults.length > 0) { callback(initialResults); } this.emit('subscription:created', { subscriptionId, agentId, query }); return subscriptionId; } unsubscribe(subscriptionId) { const subscription = this.subscriptions.get(subscriptionId); if (!subscription) return false; subscription.active = false; this.subscriptions.delete(subscriptionId); this.emit('subscription:cancelled', { subscriptionId, agentId: subscription.agentId }); return true; } notifySubscribers(item) { for (const subscription of this.subscriptions.values()) { if (!subscription.active) continue; // Check if item matches subscription query const matchingItems = this.queryIntelligence({ ...subscription.query, limit: 1 }).filter(i => i.id === item.id); if (matchingItems.length > 0) { try { subscription.callback([item]); } catch (error) { console.error(`Subscription callback failed for ${subscription.id}:`, error); } } } } async requestCollaboration(request) { request.id = request.id || crypto.randomUUID(); this.collaborationRequests.set(request.id, request); // Find agents capable of handling this request const capableAgents = this.findCapableAgents(request); // Emit collaboration request to capable agents this.emit('collaboration:request', { requestId: request.id, type: request.type, targetAgents: capableAgents, parameters: request.parameters, priority: request.priority }); // Set timeout for the request setTimeout(() => { const activeRequest = this.collaborationRequests.get(request.id); if (activeRequest) { this.emit('collaboration:timeout', { requestId: request.id, requestingAgent: request.requestingAgent }); this.collaborationRequests.delete(request.id); } }, request.timeout); return request.id; } findCapableAgents(request) { const capableAgents = []; for (const agentType of request.targetAgents) { const capabilities = this.agentCapabilities.get(agentType); if (capabilities && this.hasRequiredCapability(request, capabilities)) { capableAgents.push(agentType); } } return capableAgents; } hasRequiredCapability(request, capabilities) { // Simple capability matching - in a real system this would be more sophisticated switch (request.type) { case 'analysis': return capabilities.some(cap => cap.includes('analysis')); case 'correlation': return capabilities.includes('pattern-matching') || capabilities.includes('cross-case-analysis'); case 'validation': return capabilities.includes('validation') || capabilities.includes('verification'); case 'enhancement': return true; // Most agents can enhance data default: return false; } } submitCollaborationResult(result) { const request = this.collaborationRequests.get(result.requestId); if (!request) { console.warn(`Collaboration result submitted for unknown request: ${result.requestId}`); return; } // Emit result this.emit('collaboration:result', result); // Call callback if provided if (request.callback) { try { request.callback([result]); } catch (error) { console.error(`Collaboration callback failed for ${result.requestId}:`, error); } } // Store result as intelligence if appropriate if (result.status === 'COMPLETED' && result.confidence > 0.5) { const intelligenceItem = { id: crypto.randomUUID(), type: 'correlation', source: result.respondingAgent, timestamp: result.timestamp, confidence: result.confidence, data: result.data, tags: ['collaboration', request.type], priority: request.priority, metadata: { analysisId: result.requestId, version: '1.0', format: 'collaboration-result' } }; this.shareIntelligence(intelligenceItem); } } enhanceIntelligence(itemId, enhancement) { const item = this.intelligenceStore.get(itemId); if (!item) return false; // Create enhanced version const enhancedItem = { ...item, ...enhancement, id: crypto.randomUUID(), // New ID for enhanced version timestamp: new Date().toISOString(), metadata: { ...item.metadata, version: this.incrementVersion(item.metadata.version) } }; this.shareIntelligence(enhancedItem); this.emit('intelligence:enhanced', { originalId: itemId, enhancedId: enhancedItem.id, enhancementSource: enhancement.source }); return true; } incrementVersion(version) { const parts = version.split('.'); const major = parseInt(parts[0]) || 1; const minor = parseInt(parts[1]) || 0; const patch = parseInt(parts[2]) || 0; return `${major}.${minor}.${patch + 1}`; } correlateIntelligence(items) { const correlations = []; // Group items by type and analyze patterns const groupedItems = this.groupItemsByType(items); for (const [type, typeItems] of groupedItems.entries()) { if (typeItems.length < 2) continue; // Find correlations within the same type const typeCorrelations = this.findTypeCorrelations(type, typeItems); correlations.push(...typeCorrelations); } // Cross-type correlations const crossTypeCorrelations = this.findCrossTypeCorrelations(groupedItems); correlations.push(...crossTypeCorrelations); return correlations; } groupItemsByType(items) { const groups = new Map(); for (const item of items) { const group = groups.get(item.type) || []; group.push(item); groups.set(item.type, group); } return groups; } findTypeCorrelations(type, items) { const correlations = []; // Simple pattern detection - look for similar data values const valueMap = new Map(); for (const item of items) { const key = this.extractCorrelationKey(item); if (key) { const group = valueMap.get(key) || []; group.push(item); valueMap.set(key, group); } } // Create correlation items for groups with multiple items for (const [key, groupItems] of valueMap.entries()) { if (groupItems.length > 1) { const correlation = { id: crypto.randomUUID(), type: 'correlation', source: { type: AgentType.HUB, instance: 'intelligence-service', uuid: crypto.randomUUID() }, timestamp: new Date().toISOString(), confidence: Math.min(...groupItems.map(i => i.confidence)), data: { correlationType: 'value-match', correlationKey: key, relatedItems: groupItems.map(i => i.id), pattern: `Multiple ${type} items with matching ${key}` }, tags: ['auto-correlation', type], priority: this.determineCorrelationPriority(groupItems), metadata: { version: '1.0', format: 'auto-correlation' } }; correlations.push(correlation); } } return correlations; } extractCorrelationKey(item) { // Extract a key that can be used for correlation if (typeof item.data === 'object' && item.data !== null) { return JSON.stringify(item.data).substring(0, 100); // First 100 chars as key } if (typeof item.data === 'string') { return item.data; } return null; } findCrossTypeCorrelations(groups) { const correlations = []; // Look for temporal correlations const allItems = Array.from(groups.values()).flat(); const temporalCorrelations = this.findTemporalCorrelations(allItems); correlations.push(...temporalCorrelations); return correlations; } findTemporalCorrelations(items) { const correlations = []; const timeWindow = 300000; // 5 minutes // Sort items by timestamp const sortedItems = items.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()); // Find items within time windows for (let i = 0; i < sortedItems.length - 1; i++) { const currentTime = new Date(sortedItems[i].timestamp).getTime(); const cluster = [sortedItems[i]]; for (let j = i + 1; j < sortedItems.length; j++) { const nextTime = new Date(sortedItems[j].timestamp).getTime(); if (nextTime - currentTime <= timeWindow) { cluster.push(sortedItems[j]); } else { break; } } if (cluster.length > 1) { const correlation = { id: crypto.randomUUID(), type: 'correlation', source: { type: AgentType.HUB, instance: 'intelligence-service', uuid: crypto.randomUUID() }, timestamp: new Date().toISOString(), confidence: 0.6, data: { correlationType: 'temporal', timeWindow: timeWindow, relatedItems: cluster.map(i => i.id), pattern: `${cluster.length} intelligence items within ${timeWindow}ms` }, tags: ['temporal-correlation'], priority: 'MEDIUM', metadata: { version: '1.0', format: 'temporal-correlation' } }; correlations.push(correlation); } } return correlations; } determineCorrelationPriority(items) { const maxPriority = Math.max(...items.map(i => this.priorityToNumber(i.priority))); return this.numberToPriority(maxPriority); } priorityToNumber(priority) { switch (priority) { case 'LOW': return 1; case 'MEDIUM': return 2; case 'HIGH': return 3; case 'CRITICAL': return 4; default: return 1; } } numberToPriority(num) { switch (num) { case 4: return 'CRITICAL'; case 3: return 'HIGH'; case 2: return 'MEDIUM'; default: return 'LOW'; } } cleanupExpiredIntelligence() { const now = Date.now(); const expired = []; for (const [id, item] of this.intelligenceStore.entries()) { if (item.ttl && (new Date(item.timestamp).getTime() + item.ttl) < now) { expired.push(id); } } for (const id of expired) { this.intelligenceStore.delete(id); } if (expired.length > 0) { this.emit('intelligence:cleanup', { expiredCount: expired.length, remainingCount: this.intelligenceStore.size }); } } agentIdsEqual(a, b) { return a.type === b.type && a.instance === b.instance && a.uuid === b.uuid; } getStatistics() { const stats = { totalIntelligence: this.intelligenceStore.size, activeSubscriptions: this.subscriptions.size, activeCollaborations: this.collaborationRequests.size, intelligenceByType: new Map(), intelligenceByPriority: new Map(), averageConfidence: 0 }; let totalConfidence = 0; for (const item of this.intelligenceStore.values()) { // Count by type const typeCount = stats.intelligenceByType.get(item.type) || 0; stats.intelligenceByType.set(item.type, typeCount + 1); // Count by priority const priorityCount = stats.intelligenceByPriority.get(item.priority) || 0; stats.intelligenceByPriority.set(item.priority, priorityCount + 1); totalConfidence += item.confidence; } if (this.intelligenceStore.size > 0) { stats.averageConfidence = totalConfidence / this.intelligenceStore.size; } return stats; } destroy() { clearInterval(this.cleanupInterval); this.intelligenceStore.clear(); this.subscriptions.clear(); this.collaborationRequests.clear(); this.removeAllListeners(); } } //# sourceMappingURL=intelligence-sharing.js.map