Skip to main content
Glama
amittell

firewalla-mcp-server

get_statistics_by_box

Retrieve statistics for Firewalla boxes, identifying top performers by blocked flows or security alarms to monitor network security effectiveness.

Instructions

Get statistics for each Firewalla box (top boxes by blocked flows or security alarms)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
typeNoStatistics type to retrievetopBoxesByBlockedFlows
groupNoGet statistics for specific box group
limitNoMaximum number of results (optional, default: 5)

Implementation Reference

  • The primary handler class GetStatisticsByBoxHandler that implements the core logic for the 'get_statistics_by_box' tool. It extends BaseToolHandler, defines the tool name and description, and in the execute method calls firewalla.getStatisticsByBox() to fetch data, processes box statistics with validation, calculates summaries, and returns a unified response.
    export class GetStatisticsByBoxHandler extends BaseToolHandler { name = 'get_statistics_by_box'; description = 'Get statistics for each Firewalla box with activity scores and health monitoring. No required parameters. Data cached for 1 hour for performance.'; category = 'analytics' as const; constructor() { super({ enableGeoEnrichment: false, // No IP fields in box statistics enableFieldNormalization: true, additionalMeta: { data_source: 'box_statistics', entity_type: 'firewalla_box_statistics', supports_geographic_enrichment: false, supports_field_normalization: true, standardization_version: '2.0.0', }, }); } async execute( _args: ToolArgs, firewalla: FirewallaClient ): Promise<ToolResponse> { try { const stats = await withToolTimeout( async () => firewalla.getStatisticsByBox(), this.name ); // Validate stats response structure if (!stats || typeof stats !== 'object') { throw new Error('Invalid stats response: not an object'); } if ( !SafeAccess.getNestedValue(stats, 'results') || !Array.isArray(stats.results) ) { throw new Error('Invalid stats response: results is not an array'); } // Process and validate each box statistic const boxStatistics = SafeAccess.safeArrayMap( stats.results, (stat: any) => { const boxMeta = SafeAccess.getNestedValue(stat, 'meta', {}) as any; return { box_id: SafeAccess.getNestedValue( boxMeta, 'gid', 'unknown' ) as string, name: SafeAccess.getNestedValue( boxMeta, 'name', 'Unknown Box' ) as string, model: SafeAccess.getNestedValue( boxMeta, 'model', 'unknown' ) as string, status: (SafeAccess.getNestedValue( boxMeta, 'online', false ) as boolean) ? 'online' : 'offline', version: SafeAccess.getNestedValue( boxMeta, 'version', 'unknown' ) as string, location: SafeAccess.getNestedValue( boxMeta, 'location', 'unknown' ) as string, device_count: SafeAccess.getNestedValue( boxMeta, 'deviceCount', 0 ) as number, rule_count: SafeAccess.getNestedValue( boxMeta, 'ruleCount', 0 ) as number, alarm_count: SafeAccess.getNestedValue( boxMeta, 'alarmCount', 0 ) as number, activity_score: SafeAccess.getNestedValue( stat, 'value', 0 ) as number, last_seen: (SafeAccess.getNestedValue( boxMeta, 'lastSeen', 0 ) as number) ? unixToISOString( SafeAccess.getNestedValue(boxMeta, 'lastSeen', 0) as number ) : 'Never', }; } ).sort((a: any, b: any) => b.activity_score - a.activity_score); // Calculate summary with safe operations const onlineBoxes = SafeAccess.safeArrayFilter( stats.results, (s: any) => SafeAccess.getNestedValue(s, 'meta.online', false) as boolean ).length; const totalDevices = stats.results.reduce( (sum: number, s: any) => sum + (SafeAccess.getNestedValue(s, 'meta.deviceCount', 0) as number), 0 ); const totalRules = stats.results.reduce( (sum: number, s: any) => sum + (SafeAccess.getNestedValue(s, 'meta.ruleCount', 0) as number), 0 ); const totalAlarms = stats.results.reduce( (sum: number, s: any) => sum + (SafeAccess.getNestedValue(s, 'meta.alarmCount', 0) as number), 0 ); const startTime = Date.now(); const unifiedResponseData = { total_boxes: stats.results.length, box_statistics: boxStatistics, summary: { online_boxes: onlineBoxes, total_devices: totalDevices, total_rules: totalRules, total_alarms: totalAlarms, }, }; const executionTime = Date.now() - startTime; return this.createUnifiedResponse(unifiedResponseData, { executionTimeMs: executionTime, }); } catch (error: unknown) { logger.error( 'Error in get_statistics_by_box', error instanceof Error ? error : new Error(String(error)) ); return this.createErrorResponse( `Failed to get box statistics: ${error instanceof Error ? error.message : 'Unknown error'}`, ErrorType.API_ERROR, { total_boxes: 0, box_statistics: [], summary: { online_boxes: 0, total_devices: 0, total_rules: 0, total_alarms: 0, }, } ); } }
  • Registration of the GetStatisticsByBoxHandler in the central ToolRegistry during automatic handler registration in the constructor.
    this.register(new GetStatisticsByBoxHandler());
  • The input schema definition for the 'get_statistics_by_box' tool provided in the MCP server's listTools response, defining parameters like type, group, and limit.
    name: 'get_statistics_by_box', description: 'Get statistics for each Firewalla box (top boxes by blocked flows or security alarms)', inputSchema: { type: 'object', properties: { type: { type: 'string', enum: ['topBoxesByBlockedFlows', 'topBoxesBySecurityAlarms'], description: 'Statistics type to retrieve', default: 'topBoxesByBlockedFlows', }, group: { type: 'string', description: 'Get statistics for specific box group', }, limit: { type: 'number', description: 'Maximum number of results (optional, default: 5)', minimum: 1, default: 5, }, }, 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