Skip to main content
Glama
amittell

firewalla-mcp-server

resume_rule

Reactivate a paused firewall rule to restore its security function and network protection.

Instructions

Resume a previously paused firewall rule, restoring it to active state

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
rule_idYesRule ID to resume
boxYesBox GID for context (required by API)

Implementation Reference

  • ResumeRuleHandler class containing the execute method that implements the resume_rule tool logic: validates rule_id, checks current rule status to prevent redundant operations, calls firewalla.resumeRule(ruleId), formats unified response with success status and execution time.
    export class ResumeRuleHandler extends BaseToolHandler {
      name = 'resume_rule';
      description =
        'Resume a previously paused firewall rule. Requires rule_id parameter.';
      category = 'rule' as const;
    
      constructor() {
        super({
          enableGeoEnrichment: false, // No IP fields in rule operations
          enableFieldNormalization: true,
          additionalMeta: {
            data_source: 'rule_operations',
            entity_type: 'rule_resume_operation',
            supports_geographic_enrichment: false,
            supports_field_normalization: true,
            standardization_version: '2.0.0',
          },
        });
      }
    
      async execute(
        args: ToolArgs,
        firewalla: FirewallaClient
      ): Promise<ToolResponse> {
        try {
          // Parameter validation with enhanced rule ID format checking
          const ruleIdValidation = ParameterValidator.validateRuleId(
            args?.rule_id,
            'rule_id'
          );
    
          if (!ruleIdValidation.isValid) {
            return createErrorResponse(
              this.name,
              'Parameter validation failed',
              ErrorType.VALIDATION_ERROR,
              undefined,
              ruleIdValidation.errors
            );
          }
    
          const ruleId = ruleIdValidation.sanitizedValue as string;
    
          // Check rule status before attempting to resume it
          const statusCheck = await checkRuleStatus(ruleId, this.name, firewalla);
    
          if (!statusCheck.exists) {
            return statusCheck.errorResponse!;
          }
    
          // Prevent redundant resume operations
          if (statusCheck.isActive) {
            return createErrorResponse(
              this.name,
              'Rule is already active and does not need to be resumed',
              ErrorType.API_ERROR,
              {
                rule_id: ruleId,
                current_status: statusCheck.status,
                already_active: true,
              },
              [
                'Rule is already in an active state',
                'Use get_network_rules to verify current rule status',
                'If the rule is not working as expected, check rule configuration instead',
                'Use pause_rule if you want to temporarily disable the rule',
              ]
            );
          }
    
          // Provide helpful context for non-paused rules
          if (!statusCheck.isPaused) {
            logger.warn(
              `Rule ${ruleId} has status '${statusCheck.status}' - resuming may not activate it as expected`,
              {
                tool: 'resume_rule',
                rule_id: ruleId,
                current_status: statusCheck.status,
                warning: 'rule_not_paused',
              }
            );
          }
    
          const result = await withToolTimeout(
            async () => firewalla.resumeRule(ruleId),
            this.name
          );
    
          const startTime = Date.now();
    
          const unifiedResponseData = {
            success: SafeAccess.getNestedValue(result as any, 'success', false),
            message: SafeAccess.getNestedValue(
              result,
              'message',
              'Rule resume completed'
            ),
            rule_id: ruleId,
            action: 'resume_rule',
          };
    
          const executionTime = Date.now() - startTime;
          return this.createUnifiedResponse(unifiedResponseData, {
            executionTimeMs: executionTime,
          });
        } catch (error: unknown) {
          if (error instanceof TimeoutError) {
            return createTimeoutErrorResponse(
              this.name,
              error.duration,
              10000 // Default timeout
            );
          }
    
          const errorMessage =
            error instanceof Error ? error.message : 'Unknown error occurred';
          return this.createErrorResponse(`Failed to resume rule: ${errorMessage}`);
        }
      }
    }
  • Registration of the ResumeRuleHandler instance in the ToolRegistry constructor's registerHandlers method.
    this.register(new ResumeRuleHandler());
  • Input schema definition for the resume_rule tool provided in the static ListToolsRequestSchema response, specifying required rule_id and box parameters.
      name: 'resume_rule',
      description:
        'Resume a previously paused firewall rule, restoring it to active state',
      inputSchema: {
        type: 'object',
        properties: {
          rule_id: {
            type: 'string',
            description: 'Rule ID to resume',
          },
          box: {
            type: 'string',
            description: 'Box GID for context (required by API)',
          },
        },
        required: ['rule_id', 'box'],
      },
    },
  • checkRuleStatus utility function used by ResumeRuleHandler (and PauseRuleHandler) to validate rule existence, check current status (active/paused), and prevent redundant operations before calling the resume API.
    async function checkRuleStatus(
      ruleId: string,
      toolName: string,
      firewalla: FirewallaClient
    ): Promise<RuleStatusInfo> {
      try {
        // First check if the rule exists
        const existenceCheck = await validateRuleExists(
          ruleId,
          toolName,
          firewalla
        );
        if (!existenceCheck.exists) {
          return {
            exists: false,
            status: 'not_found',
            isPaused: false,
            isActive: false,
            errorResponse: existenceCheck.errorResponse,
          };
        }
    
        // Get the specific rule details to check its status
        const rulesResponse = await firewalla.getNetworkRules(`id:${ruleId}`, 1);
        const rules = SafeAccess.getNestedValue(
          rulesResponse,
          'results',
          []
        ) as any[];
    
        if (rules.length === 0) {
          return {
            exists: false,
            status: 'not_found',
            isPaused: false,
            isActive: false,
            errorResponse: createErrorResponse(
              toolName,
              'Rule not found in current rule set',
              ErrorType.API_ERROR,
              { rule_id: ruleId }
            ),
          };
        }
    
        const rule = rules[0];
        const status = SafeAccess.getNestedValue(
          rule,
          'status',
          'unknown'
        ) as string;
        const resumeTs = SafeAccess.getNestedValue(rule, 'resumeTs', undefined) as
          | number
          | undefined;
    
        // Determine if rule is paused or active
        const isPaused: boolean =
          status === 'paused' ||
          status === 'disabled' ||
          Boolean(resumeTs && resumeTs > Date.now() / 1000);
        const isActive: boolean = status === 'active' || status === 'enabled';
    
        return {
          exists: true,
          status,
          isPaused,
          isActive,
          resumeAt: resumeTs ? new Date(resumeTs * 1000).toISOString() : undefined,
        };
      } catch (error) {
        return {
          exists: false,
          status: 'error',
          isPaused: false,
          isActive: false,
          errorResponse: createErrorResponse(
            toolName,
            `Failed to check rule status: ${error instanceof Error ? error.message : 'Unknown error'}`,
            ErrorType.API_ERROR,
            { rule_id: ruleId }
          ),
        };
      }
    }
Behavior2/5

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

No annotations are provided, so the description carries the full burden. It states the tool performs a mutation ('Resume'), implying it changes the rule state, but lacks details on permissions required, whether the action is reversible, error conditions, or rate limits. This is a significant gap for a mutation tool with zero annotation coverage.

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 a single, efficient sentence with no wasted words. It is front-loaded with the core action and outcome, making it easy to understand quickly. Every part of the sentence contributes directly to the tool's purpose.

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

Completeness2/5

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

Given this is a mutation tool with no annotations and no output schema, the description is incomplete. It lacks information on behavioral traits like side effects, error handling, or return values. While concise, it does not provide enough context for safe and effective use by an AI agent.

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 fully documents both parameters ('rule_id' and 'box'). The description does not add any meaning beyond the schema, such as explaining parameter relationships or usage context. Baseline 3 is appropriate when the schema handles all 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 action ('Resume'), the resource ('a previously paused firewall rule'), and the outcome ('restoring it to active state'). It uses specific verbs and distinguishes itself from siblings like 'pause_rule' by indicating the opposite operation.

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

Usage Guidelines3/5

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

The description implies usage by mentioning 'previously paused firewall rule,' suggesting it should be used only on rules that are currently paused. However, it does not explicitly state when to use this tool versus alternatives like 'pause_rule' or other rule-management tools, nor does it provide exclusions or prerequisites.

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