Skip to main content
Glama
amittell

firewalla-mcp-server

get_flow_insights

Analyze network traffic by content category to identify bandwidth usage, top content types, and blocked traffic patterns for security monitoring.

Instructions

Get category-based flow analysis including top content categories, bandwidth consumers, and blocked traffic. Ideal for answering questions like "what porn sites were accessed" or "what social media was used". Replaces time-based trends with actionable insights.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
periodNoTime period for analysis (default: 24h)24h
categoriesNoFilter to specific content categories (optional)
include_blockedNoInclude blocked traffic analysis (default: false)

Implementation Reference

  • The GetFlowInsightsHandler class implements the core logic for the 'get_flow_insights' tool. It validates parameters (period, categories, include_blocked), calls the Firewalla API via firewalla.getFlowInsights, processes the response with normalization and formatting, and returns a unified response structure.
    export class GetFlowInsightsHandler extends BaseToolHandler {
      name = 'get_flow_insights';
      description =
        'Get category-based flow analysis including top content categories, bandwidth consumers, and blocked traffic. Replaces time-based trends with actionable insights for networks with high flow volumes. Ideal for answering questions like "what porn sites were accessed" or "what social media was used".';
      category = 'analytics' as const;
    
      constructor() {
        super({
          enableGeoEnrichment: false, // Already contains aggregated data
          enableFieldNormalization: true,
          additionalMeta: {
            data_source: 'flow_insights',
            entity_type: 'category_flow_analysis',
            supports_geographic_enrichment: false,
            supports_field_normalization: true,
            standardization_version: '2.0.0',
          },
        });
      }
    
      async execute(
        _args: ToolArgs,
        firewalla: FirewallaClient
      ): Promise<ToolResponse> {
        try {
          const periodValidation = ParameterValidator.validateEnum(
            _args?.period,
            'period',
            ['1h', '24h', '7d', '30d'],
            false,
            '24h'
          );
          const categoriesValidation = ParameterValidator.validateArray(
            _args?.categories,
            'categories',
            {
              required: false,
            }
          );
    
          // Validate allowed category values if provided
          const allowedCategories = [
            'ad',
            'edu',
            'games',
            'gamble',
            'intel',
            'p2p',
            'porn',
            'private',
            'social',
            'shopping',
            'video',
            'vpn',
          ];
    
          if (categoriesValidation.isValid && categoriesValidation.sanitizedValue) {
            const categories = categoriesValidation.sanitizedValue as string[];
            const invalidCategories = categories.filter(
              cat => !allowedCategories.includes(cat)
            );
            if (invalidCategories.length > 0) {
              categoriesValidation.isValid = false;
              categoriesValidation.errors = [
                `Invalid categories: ${invalidCategories.join(', ')}`,
              ];
            }
          }
          const includeBlockedValidation = ParameterValidator.validateBoolean(
            _args?.include_blocked,
            'include_blocked',
            false
          );
    
          const validationResult = ParameterValidator.combineValidationResults([
            periodValidation,
            categoriesValidation,
            includeBlockedValidation,
          ]);
    
          if (!validationResult.isValid) {
            return this.createErrorResponse(
              'Parameter validation failed',
              ErrorType.VALIDATION_ERROR,
              undefined,
              validationResult.errors
            );
          }
    
          const period = periodValidation.sanitizedValue as
            | '1h'
            | '24h'
            | '7d'
            | '30d';
          const categories = categoriesValidation.sanitizedValue as
            | string[]
            | undefined;
          const includeBlocked = includeBlockedValidation.sanitizedValue as boolean;
    
          const startTime = Date.now();
    
          const insights = await withToolTimeout(
            async () =>
              firewalla.getFlowInsights(period, {
                categories,
                includeBlocked,
              }),
            this.name
          );
    
          // Format response for better readability
          const unifiedResponseData = {
            period,
            analysis_time: getCurrentTimestamp(),
    
            // Category breakdown with human-readable formatting
            content_categories: insights.categoryBreakdown.map(cat => ({
              category: cat.category,
              flow_count: cat.count,
              total_bytes: cat.bytes,
              total_mb: Math.round((cat.bytes / 1048576) * 100) / 100,
              top_domains: cat.topDomains.map(dom => ({
                domain: dom.domain,
                visits: dom.count,
                bandwidth_mb: Math.round((dom.bytes / 1048576) * 100) / 100,
              })),
            })),
    
            // Top bandwidth consumers
            top_bandwidth_devices: insights.topDevices.map(dev => ({
              device: dev.device,
              total_bandwidth_mb:
                Math.round((dev.totalBytes / 1048576) * 100) / 100,
              category_usage: dev.categories.map(cat => ({
                category: cat.category,
                bandwidth_mb: Math.round((cat.bytes / 1048576) * 100) / 100,
              })),
            })),
    
            // Blocked traffic summary if requested
            ...(insights.blockedSummary && {
              blocked_traffic: {
                total_blocked_flows: insights.blockedSummary.totalBlocked,
                blocked_by_category: insights.blockedSummary.byCategory,
              },
            }),
    
            // Summary statistics
            summary: {
              total_categories: insights.categoryBreakdown.length,
              total_bandwidth_gb:
                Math.round(
                  (insights.categoryBreakdown.reduce(
                    (sum, cat) => sum + cat.bytes,
                    0
                  ) /
                    1073741824) *
                    100
                ) / 100,
              most_active_category:
                insights.categoryBreakdown[0]?.category || 'none',
              top_bandwidth_consumer: insights.topDevices[0]?.device || 'none',
            },
          };
    
          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 flow insights: ${errorMessage}`,
            ErrorType.API_ERROR,
            {
              period: _args?.period || '24h',
              categories: _args?.categories || 'all',
              troubleshooting:
                'Check if Firewalla API is accessible and flow data is available',
            }
          );
        }
      }
    }
  • Registration of the GetFlowInsightsHandler instance in the ToolRegistry during automatic tool registration.
    this.register(new GetFlowInsightsHandler());
  • MCP tool schema definition in server.ts, specifying the inputSchema with parameters period (enum), categories (array of allowed categories), and include_blocked (boolean) for the get_flow_insights tool.
      name: 'get_flow_insights',
      description:
        'Get category-based flow analysis including top content categories, bandwidth consumers, and blocked traffic. Ideal for answering questions like "what porn sites were accessed" or "what social media was used". Replaces time-based trends with actionable insights.',
      inputSchema: {
        type: 'object',
        properties: {
          period: {
            type: 'string',
            enum: ['1h', '24h', '7d', '30d'],
            description: 'Time period for analysis (default: 24h)',
            default: '24h',
          },
          categories: {
            type: 'array',
            items: {
              type: 'string',
              enum: [
                'ad',
                'edu',
                'games',
                'gamble',
                'intel',
                'p2p',
                'porn',
                'private',
                'social',
                'shopping',
                'video',
                'vpn',
              ],
            },
            description:
              'Filter to specific content categories (optional)',
          },
          include_blocked: {
            type: 'boolean',
            description:
              'Include blocked traffic analysis (default: false)',
            default: false,
          },
        },
        required: [],
      },
    },
  • Import statement for GetFlowInsightsHandler from './handlers/analytics.js' in the ToolRegistry file.
    GetFlowInsightsHandler,
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes what the tool does (analysis of categories, bandwidth, blocked traffic) and provides example use cases, but lacks details on permissions, rate limits, response format, or potential side effects. It's adequate but not comprehensive for a tool with no annotation support.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is perfectly concise and well-structured with three sentences that each serve distinct purposes: stating the core functionality, providing concrete usage examples, and differentiating from alternatives. Every sentence earns its place with zero wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no annotations and no output schema, the description does well at explaining what the tool provides (actionable insights) and when to use it. However, it lacks details about the return format or structure of insights, which would be helpful given the absence of output schema. The description is complete enough for basic understanding but could better address output expectations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents all three parameters. The description adds no additional parameter semantics beyond what's in the schema - it doesn't explain how parameters interact or provide usage examples with specific parameter values. Baseline 3 is appropriate when schema does all the parameter documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('Get category-based flow analysis') and resources ('top content categories, bandwidth consumers, and blocked traffic'). It distinguishes from siblings by focusing on actionable insights rather than time-based trends, unlike tools like get_bandwidth_usage or get_flow_data which may provide different types of data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage guidance with examples ('Ideal for answering questions like "what porn sites were accessed" or "what social media was used"') and distinguishes when to use this tool versus alternatives ('Replaces time-based trends with actionable insights'), clearly differentiating it from trend-focused sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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