Skip to main content
Glama

update_rules

Modify audit rules configuration for Blind-Auditor-MCP to add, remove, update, or list security and compliance rules.

Instructions

Update audit rules configuration. Args: action: Operation to perform - "add", "remove", "update", or "list" rule_id: Rule identifier (required for add/remove/update) severity: Rule severity level - "CRITICAL", "WARNING", or "PREFERENCE" (for add/update) description: Rule description (for add/update) weight: Point deduction weight 0-100 (for add/update) Returns: Status message with operation result Examples: # List all rules update_rules(action="list") # Add a new rule update_rules( action="add", rule_id="SEC-001", severity="CRITICAL", description="No hardcoded API keys", weight=50 ) # Remove a rule update_rules(action="remove", rule_id="SEC-001") # Update a rule update_rules( action="update", rule_id="SEC-001", description="Updated description" )

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYes
rule_idNo
severityNo
descriptionNo
weightNo

Implementation Reference

  • The primary handler function for the 'update_rules' tool, decorated with @mcp.tool() for registration. Implements logic for listing, adding, removing, and updating audit rules by delegating to RulesLoader instance.
    @mcp.tool() def update_rules( action: str, rule_id: str = "", severity: str = "", description: str = "", weight: int = 0 ) -> str: """ Update audit rules configuration. Args: action: Operation to perform - "add", "remove", "update", or "list" rule_id: Rule identifier (required for add/remove/update) severity: Rule severity level - "CRITICAL", "WARNING", or "PREFERENCE" (for add/update) description: Rule description (for add/update) weight: Point deduction weight 0-100 (for add/update) Returns: Status message with operation result Examples: # List all rules update_rules(action="list") # Add a new rule update_rules( action="add", rule_id="SEC-001", severity="CRITICAL", description="No hardcoded API keys", weight=50 ) # Remove a rule update_rules(action="remove", rule_id="SEC-001") # Update a rule update_rules( action="update", rule_id="SEC-001", description="Updated description" ) """ print(f"DEBUG: update_rules called with action={action}, rule_id={rule_id}", file=sys.stderr) # Reload rules to get latest state rules_loader.load() # Handle list action if action == "list": return rules_loader.list_rules() # Validate rule_id for non-list actions if not rule_id: return "❌ Error: rule_id is required for add/remove/update actions." # Handle add action if action == "add": if not severity or not description: return "❌ Error: severity and description are required for adding a rule." result = rules_loader.add_rule(rule_id, severity, description, weight) if result["status"] == "success": return f"✅ {result['message']}\n\n{rules_loader.list_rules()}" else: return f"❌ {result['message']}" # Handle remove action elif action == "remove": result = rules_loader.remove_rule(rule_id) if result["status"] == "success": return f"✅ {result['message']}\n\n{rules_loader.list_rules()}" else: return f"❌ {result['message']}" # Handle update action elif action == "update": # Only pass non-empty values update_kwargs = {} if severity: update_kwargs["severity"] = severity if description: update_kwargs["description"] = description if weight > 0: update_kwargs["weight"] = weight if not update_kwargs: return "❌ Error: At least one field (severity, description, or weight) must be provided for update." result = rules_loader.update_rule(rule_id, **update_kwargs) if result["status"] == "success": return f"✅ {result['message']}\n\n{rules_loader.list_rules()}" else: return f"❌ {result['message']}" else: return f"❌ Error: Invalid action '{action}'. Must be one of: add, remove, update, list"
  • The RulesLoader class containing all helper methods (load, add_rule, remove_rule, update_rule, list_rules) called by the update_rules handler to manage the rules.json file.
    class RulesLoader: """Loads and manages audit rules from rules.json.""" def __init__(self, rules_path: str = "rules.json"): self.rules_path = Path(rules_path) self.rules_data: Dict[str, Any] = {} def load(self) -> Dict[str, Any]: """Load rules from the JSON file.""" if not self.rules_path.exists(): # Return default empty structure return { "project_name": "Unknown", "strict_mode": True, "max_retries": 3, "rules": [] } with open(self.rules_path, 'r', encoding='utf-8') as f: self.rules_data = json.load(f) return self.rules_data def save(self) -> None: """Save current rules data back to JSON file.""" with open(self.rules_path, 'w', encoding='utf-8') as f: json.dump(self.rules_data, f, indent=2, ensure_ascii=False) def get_rules(self) -> List[Dict[str, Any]]: """Get the list of rules.""" return self.rules_data.get("rules", []) def get_max_retries(self) -> int: """Get the maximum retry count.""" return self.rules_data.get("max_retries", 3) def add_rule(self, rule_id: str, severity: str, description: str, weight: int) -> Dict[str, str]: """ Add a new rule to the rules list. Args: rule_id: Unique identifier for the rule (e.g., "SEC-001") severity: Rule severity level ("CRITICAL", "WARNING", "PREFERENCE") description: Description of the rule weight: Point deduction weight for violations Returns: Dict with status and message """ # Validate severity valid_severities = ["CRITICAL", "WARNING", "PREFERENCE"] if severity not in valid_severities: return { "status": "error", "message": f"Invalid severity '{severity}'. Must be one of: {', '.join(valid_severities)}" } # Check for duplicate rule_id existing_rules = self.get_rules() if any(rule.get("id") == rule_id for rule in existing_rules): return { "status": "error", "message": f"Rule with ID '{rule_id}' already exists. Use update_rule to modify it." } # Validate weight if not isinstance(weight, int) or weight < 0 or weight > 100: return { "status": "error", "message": f"Weight must be an integer between 0 and 100, got {weight}" } # Add the new rule new_rule = { "id": rule_id, "severity": severity, "description": description, "weight": weight } self.rules_data["rules"].append(new_rule) self.save() return { "status": "success", "message": f"Rule '{rule_id}' added successfully." } def remove_rule(self, rule_id: str) -> Dict[str, str]: """ Remove a rule by its ID. Args: rule_id: The ID of the rule to remove Returns: Dict with status and message """ existing_rules = self.get_rules() original_count = len(existing_rules) # Filter out the rule with matching ID self.rules_data["rules"] = [ rule for rule in existing_rules if rule.get("id") != rule_id ] if len(self.rules_data["rules"]) == original_count: return { "status": "error", "message": f"Rule with ID '{rule_id}' not found." } self.save() return { "status": "success", "message": f"Rule '{rule_id}' removed successfully." } def update_rule( self, rule_id: str, severity: Optional[str] = None, description: Optional[str] = None, weight: Optional[int] = None ) -> Dict[str, str]: """ Update an existing rule. Args: rule_id: The ID of the rule to update severity: New severity level (optional) description: New description (optional) weight: New weight (optional) Returns: Dict with status and message """ existing_rules = self.get_rules() rule_found = False for rule in existing_rules: if rule.get("id") == rule_id: rule_found = True # Validate and update severity if severity is not None: valid_severities = ["CRITICAL", "WARNING", "PREFERENCE"] if severity not in valid_severities: return { "status": "error", "message": f"Invalid severity '{severity}'. Must be one of: {', '.join(valid_severities)}" } rule["severity"] = severity # Update description if description is not None: rule["description"] = description # Validate and update weight if weight is not None: if not isinstance(weight, int) or weight < 0 or weight > 100: return { "status": "error", "message": f"Weight must be an integer between 0 and 100, got {weight}" } rule["weight"] = weight break if not rule_found: return { "status": "error", "message": f"Rule with ID '{rule_id}' not found." } self.save() return { "status": "success", "message": f"Rule '{rule_id}' updated successfully." } def list_rules(self) -> str: """ Get a formatted string of all current rules. Returns: Formatted string listing all rules """ rules = self.get_rules() if not rules: return "No rules configured." lines = ["Current Audit Rules:", ""] for i, rule in enumerate(rules, 1): lines.append(f"{i}. [{rule.get('severity', 'UNKNOWN')}] {rule.get('id', 'NO_ID')}") lines.append(f" Description: {rule.get('description', 'No description')}") lines.append(f" Weight: {rule.get('weight', 0)} points") lines.append("") return "\n".join(lines) def format_rules_for_prompt(self) -> str: """Format rules as a readable string for prompt injection.""" rules = self.get_rules() if not rules: return "No rules configured." formatted = [] for rule in rules: severity = rule.get("severity", "UNKNOWN") description = rule.get("description", "") rule_id = rule.get("id", "") formatted.append(f"[{severity}] {rule_id}: {description}") return "\n".join(formatted)
  • src/main.py:14-22 (registration)
    MCP server initialization and run, where tools including update_rules are registered via decorators and exposed via mcp.run().
    from mcp.server.fastmcp import FastMCP print("DEBUG: Importing state and rules", file=sys.stderr) from state import SessionState from rules import RulesLoader # Initialize the MCP server print("DEBUG: Creating FastMCP instance", file=sys.stderr) mcp = FastMCP("Blind Auditor")

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/Sim-xia/Blind-Audition-MCP'

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