get_recent_flow_activity
Retrieve a snapshot of recent network flows for immediate security threat detection and current network issue analysis. Provides up to 50 most recent flows from the last 10-20 minutes.
Instructions
Get recent network flow activity snapshot (last 10-20 minutes). Returns up to 50 most recent flows for immediate analysis. CRITICAL: This is a quick snapshot tool only. Use this for: "what's happening right now?", current security threats, immediate network issues. DO NOT use for: historical analysis (use search_flows), getting more than 50 flows (use search_flows with limit), daily/weekly patterns (use search_flows with time queries like "ts:>24h"). For comprehensive analysis, always prefer search_flows.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/handlers/analytics.ts:580-788 (handler)GetRecentFlowActivityHandler class: core implementation that fetches up to 50 recent network flows (last 10-20 min), analyzes protocols/regions/blocked flows, and returns formatted snapshot for immediate network activity assessment.export class GetRecentFlowActivityHandler extends BaseToolHandler { name = 'get_recent_flow_activity'; description = 'Get recent network flow activity snapshot (last 10-20 minutes of traffic). Returns up to 50 most recent flows for immediate analysis. IMPORTANT: This is NOT historical trend data - it shows current activity only. Use for "what\'s happening now" questions, not daily/weekly patterns. Ideal for: current security assessment, immediate network state, recent protocol distribution.'; category = 'analytics' as const; private static readonly MAX_FLOWS = 50; private static readonly FLOWS_PER_PAGE = 50; private static readonly MAX_PAGES = Math.ceil( GetRecentFlowActivityHandler.MAX_FLOWS / GetRecentFlowActivityHandler.FLOWS_PER_PAGE ); constructor() { super({ enableGeoEnrichment: false, // Disabled to stay within token limits enableFieldNormalization: true, additionalMeta: { data_source: 'recent_flow_activity', entity_type: 'current_network_snapshot', supports_geographic_enrichment: false, supports_field_normalization: true, standardization_version: '2.0.0', time_scope: 'recent_activity_only', max_flows: GetRecentFlowActivityHandler.MAX_FLOWS, }, }); } async execute( _args: ToolArgs, firewalla: FirewallaClient ): Promise<ToolResponse> { try { const startTime = Date.now(); const allFlows: any[] = []; let cursor: string | undefined; let pagesProcessed = 0; // Fetch up to 2000 flows in 4 pages of 500 each while ( pagesProcessed < GetRecentFlowActivityHandler.MAX_PAGES && allFlows.length < GetRecentFlowActivityHandler.MAX_FLOWS ) { const currentCursor = cursor; const pageData = await withToolTimeout( async () => firewalla.getFlowData( undefined, // No query filter - get all recent flows undefined, // No groupBy - we want individual flows 'ts:desc', // Most recent first GetRecentFlowActivityHandler.FLOWS_PER_PAGE, currentCursor ), this.name ); if (!pageData?.results || !Array.isArray(pageData.results)) { break; // No more data or invalid response } allFlows.push(...pageData.results); cursor = pageData.next_cursor; pagesProcessed++; // Break if no more pages available or we hit our limit if ( !cursor || allFlows.length >= GetRecentFlowActivityHandler.MAX_FLOWS ) { break; } } // Limit to exactly MAX_FLOWS if we got more const flows = allFlows.slice(0, GetRecentFlowActivityHandler.MAX_FLOWS); if (flows.length === 0) { return this.createUnifiedResponse( { flows_analyzed: 0, time_span_minutes: 0, activity_summary: 'No recent flows found', flows: [], limitations: { data_scope: 'Current activity snapshot only', not_suitable_for: [ 'Historical analysis', 'Daily patterns', 'Trend analysis', ], time_frame: 'Last 10-20 minutes for high-volume networks', }, }, { executionTimeMs: Date.now() - startTime, } ); } // Calculate time span of the flows const oldestFlow = flows[flows.length - 1]; const newestFlow = flows[0]; const timeSpanSeconds = (newestFlow.ts || 0) - (oldestFlow.ts || 0); const timeSpanMinutes = Math.round(timeSpanSeconds / 60); // Analyze the flows for summary statistics const protocolCounts = new Map<string, number>(); const regionCounts = new Map<string, number>(); const blockedCount = flows.filter(f => f.block).length; const allowedCount = flows.length - blockedCount; flows.forEach(flow => { const protocol = flow.protocol || 'unknown'; const region = flow.region || flow.country || 'unknown'; protocolCounts.set(protocol, (protocolCounts.get(protocol) || 0) + 1); regionCounts.set(region, (regionCounts.get(region) || 0) + 1); }); // Convert maps to sorted arrays for top protocols/regions const topProtocols = Array.from(protocolCounts.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, 5) .map(([protocol, count]) => ({ protocol, count, percentage: Math.round((count / flows.length) * 100), })); const topRegions = Array.from(regionCounts.entries()) .sort((a, b) => b[1] - a[1]) .slice(0, 5) .map(([region, count]) => ({ region, count, percentage: Math.round((count / flows.length) * 100), })); const unifiedResponseData = { flows_analyzed: flows.length, pages_fetched: pagesProcessed, time_span_minutes: timeSpanMinutes, data_period: `Last ${timeSpanMinutes} minutes`, activity_summary: { total_flows: flows.length, blocked_flows: blockedCount, allowed_flows: allowedCount, blocked_percentage: Math.round((blockedCount / flows.length) * 100), top_protocols: topProtocols, top_regions: topRegions, }, flows: flows.map(flow => ({ timestamp: flow.ts, timestamp_iso: safeUnixToISOString(flow.ts, 'Never'), protocol: flow.protocol, direction: flow.direction, blocked: flow.block, source_ip: flow.source?.ip, destination_ip: flow.destination?.ip, region: flow.region || flow.country, category: flow.category, domain: flow.domain, bytes: flow.total || 0, block_reason: flow.blockedby, })), limitations: { data_scope: 'Recent activity snapshot only - NOT historical trends', sample_size: `${flows.length} flows from last ${timeSpanMinutes} minutes`, not_suitable_for: [ 'Daily/weekly/monthly analysis', 'Historical trend identification', 'Peak usage time analysis', 'Long-term pattern detection', ], suitable_for: [ 'Current network state assessment', 'Immediate security analysis', 'Recent protocol distribution', 'Active threat detection', 'Real-time activity monitoring', ], performance_note: flows.length >= GetRecentFlowActivityHandler.MAX_FLOWS ? `Limited to ${GetRecentFlowActivityHandler.MAX_FLOWS} flows for performance` : 'All available recent flows included', }, }; const executionTime = Date.now() - startTime; return this.createUnifiedResponse(unifiedResponseData, { executionTimeMs: executionTime, }); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; return this.createErrorResponse( `Failed to get recent flow activity: ${errorMessage}`, ErrorType.API_ERROR, { max_flows: GetRecentFlowActivityHandler.MAX_FLOWS, flows_per_page: GetRecentFlowActivityHandler.FLOWS_PER_PAGE, troubleshooting: 'Check if Firewalla API is accessible and credentials are valid', } ); } } }
- src/tools/registry.ts:165-165 (registration)Tool registration in ToolRegistry constructor: instantiates and registers the handler with the MCP tool registry.this.register(new GetRecentFlowActivityHandler());
- src/server.ts:604-612 (schema)MCP protocol tool schema: defines name, detailed description emphasizing current snapshot use-case, and empty input schema (no parameters required).name: 'get_recent_flow_activity', description: 'Get recent network flow activity snapshot (last 10-20 minutes). Returns up to 50 most recent flows for immediate analysis. CRITICAL: This is a quick snapshot tool only. Use this for: "what\'s happening right now?", current security threats, immediate network issues. DO NOT use for: historical analysis (use search_flows), getting more than 50 flows (use search_flows with limit), daily/weekly patterns (use search_flows with time queries like "ts:>24h"). For comprehensive analysis, always prefer search_flows.', inputSchema: { type: 'object', properties: {}, required: [], }, },