Skip to main content
Glama
dkruyt

Hetzner Cloud MCP Server

by dkruyt

apply_firewall_to_resources

Apply firewall rules to Hetzner Cloud servers or server groups using specific IDs or label selectors to control network access.

Instructions

Apply a firewall to resources.

Applies a firewall to multiple resources like servers or server groups by label.

Examples:
- Apply to server: {"firewall_id": 12345, "resources": [{"type": "server", "server_id": 123}]}
- Apply by label: {"firewall_id": 12345, "resources": [{"type": "label_selector", "label_selector": "env=prod"}]}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
paramsYes

Implementation Reference

  • The handler function decorated with @mcp.tool() that implements the logic for applying a firewall to specified servers or label-selected resources using the Hetzner Cloud client API. It validates inputs, converts params to domain objects, calls apply_to_resources, and returns actions.
    @mcp.tool()
    def apply_firewall_to_resources(params: FirewallResourcesParams) -> Dict[str, Any]:
        """
        Apply a firewall to resources.
        
        Applies a firewall to multiple resources like servers or server groups by label.
        
        Examples:
        - Apply to server: {"firewall_id": 12345, "resources": [{"type": "server", "server_id": 123}]}
        - Apply by label: {"firewall_id": 12345, "resources": [{"type": "label_selector", "label_selector": "env=prod"}]}
        """
        try:
            firewall = client.firewalls.get_by_id(params.firewall_id)
            if not firewall:
                return {"error": f"Firewall with ID {params.firewall_id} not found"}
            
            # Convert resource parameters to FirewallResource objects
            resources = []
            for resource_param in params.resources:
                if resource_param.type == "server":
                    if not resource_param.server_id:
                        return {"error": "Server ID is required when resource type is 'server'"}
                    server = client.servers.get_by_id(resource_param.server_id)
                    if not server:
                        return {"error": f"Server with ID {resource_param.server_id} not found"}
                    resource = FirewallResource(type=resource_param.type, server=server)
                elif resource_param.type == "label_selector":
                    if not resource_param.label_selector:
                        return {"error": "Label selector is required when resource type is 'label_selector'"}
                    label_selector = FirewallResourceLabelSelector(selector=resource_param.label_selector)
                    resource = FirewallResource(type=resource_param.type, label_selector=label_selector)
                else:
                    return {"error": f"Invalid resource type: {resource_param.type}. Must be 'server' or 'label_selector'"}
                resources.append(resource)
            
            # Apply the firewall to the resources
            actions = client.firewalls.apply_to_resources(firewall, resources)
            
            # Format the response
            return {
                "success": True,
                "actions": [
                    {
                        "id": action.id,
                        "status": action.status,
                        "command": action.command,
                        "progress": action.progress,
                        "error": action.error,
                        "started": action.started.isoformat() if action.started else None,
                        "finished": action.finished.isoformat() if action.finished else None,
                    }
                    for action in actions
                ] if actions else None,
            }
        except Exception as e:
            return {"error": f"Failed to apply firewall to resources: {str(e)}"}
  • Pydantic BaseModel classes defining the input parameters for the tool: FirewallResourceParam for individual resources and FirewallResourcesParams as the top-level input schema requiring firewall_id and list of resources.
    class FirewallResourceParam(BaseModel):
        type: str = Field(..., description="Type of resource ('server' or 'label_selector')")
        server_id: Optional[int] = Field(None, description="Server ID (required when type is 'server')")
        label_selector: Optional[str] = Field(None, description="Label selector (required when type is 'label_selector')")
    
    # Create Firewall Parameter Model
    class CreateFirewallParams(BaseModel):
        name: str = Field(..., description="Name of the firewall")
        rules: Optional[List[FirewallRuleParam]] = Field(None, description="List of firewall rules")
        resources: Optional[List[FirewallResourceParam]] = Field(None, description="List of resources to apply the firewall to")
        labels: Optional[Dict[str, str]] = Field(None, description="User-defined labels (key-value pairs)")
    
    # Update Firewall Parameter Model
    class UpdateFirewallParams(BaseModel):
        firewall_id: int = Field(..., description="The ID of the firewall")
        name: Optional[str] = Field(None, description="New name for the firewall")
        labels: Optional[Dict[str, str]] = Field(None, description="User-defined labels (key-value pairs)")
    
    # Set Firewall Rules Parameter Model
    class SetFirewallRulesParams(BaseModel):
        firewall_id: int = Field(..., description="The ID of the firewall")
        rules: List[FirewallRuleParam] = Field(..., description="List of firewall rules")
    
    # Apply/Remove Firewall Resources Parameter Model
    class FirewallResourcesParams(BaseModel):
        firewall_id: int = Field(..., description="The ID of the firewall")
        resources: List[FirewallResourceParam] = Field(..., description="List of resources to apply/remove the firewall to/from")

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/dkruyt/mcp-hetzner'

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