Skip to main content
Glama
amittell

firewalla-mcp-server

get_flow_insights

Analyze network traffic by content categories to identify top bandwidth consumers, blocked traffic, and usage trends for sites like social media or adult content. Provides actionable insights for period-specific 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
categoriesNoFilter to specific content categories (optional)
include_blockedNoInclude blocked traffic analysis (default: false)
periodNoTime period for analysis (default: 24h)24h

Implementation Reference

  • GetFlowInsightsHandler class: implements the core tool execution logic. Validates inputs (period, categories, include_blocked), calls firewalla.getFlowInsights(), processes response into structured insights (categories, top devices, blocked traffic, summaries), handles errors, and returns formatted ToolResponse.
    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', } ); } } }
  • Tool registration: GetFlowInsightsHandler is instantiated and registered in the ToolRegistry during construction.
    this.register(new GetFlowInsightsHandler());
  • Input schema definition for get_flow_insights tool, including parameters period (enum), categories (array enum), include_blocked (boolean), as exposed in the MCP listTools response.
    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.
    GetFlowInsightsHandler,

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