Skip to main content
Glama
amittell

firewalla-mcp-server

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

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • 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',
            }
          );
        }
      }
    }
  • Tool registration in ToolRegistry constructor: instantiates and registers the handler with the MCP tool registry.
    this.register(new GetRecentFlowActivityHandler());
  • 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: [],
      },
    },

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/amittell/firewalla-mcp-server'

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