Skip to main content
Glama
params.py7.24 kB
"""Parameter models for FastMCP tool validation.""" from typing import Annotated, Any, Literal from pydantic import Field, StringConstraints, computed_field, field_validator from .container import MCPModel # Import Enum types from .enums import ComposeAction, ContainerAction, HostAction # Type aliases for string constraints DNSName = Annotated[ str, StringConstraints(max_length=63, pattern=r"^$|^[a-z0-9]([-a-z0-9]*[a-z0-9])?$") ] def _validate_enum_action(value: Any, enum_class: type) -> Any: """Generic validator for enum action fields.""" if isinstance(value, str): # Handle "EnumClass.VALUE" format if "." in value: enum_value = value.split(".")[-1].lower() else: enum_value = value.lower() # Match by value or name for action in enum_class: if action.value == enum_value or action.name.lower() == enum_value: return action elif isinstance(value, enum_class): return value # Let Pydantic handle the error if no match return value class DockerHostsParams(MCPModel): """Parameters for the docker_hosts consolidated tool.""" action: HostAction = Field( default=HostAction.LIST, description="Action to perform (defaults to list if not provided)" ) ssh_host: str = Field(default="", description="SSH hostname or IP address") ssh_user: str = Field(default="", description="SSH username") ssh_port: int = Field(default=22, ge=1, le=65535, description="SSH port number") ssh_key_path: str | None = Field(default=None, description="Path to SSH private key file") description: str = Field(default="", description="Host description") tags: list[str] = Field(default_factory=list, description="Host tags") compose_path: str | None = Field(default=None, description="Docker Compose file path") appdata_path: str | None = Field(default=None, description="Application data storage path") enabled: bool = Field(default=True, description="Whether host is enabled") ssh_config_path: str | None = Field(default=None, description="Path to SSH config file") selected_hosts: str | None = Field( default=None, description="Comma-separated list of hosts to select" ) cleanup_type: Literal["check", "safe", "moderate", "aggressive"] | None = Field( default=None, description="Type of cleanup to perform" ) host_id: str = Field(default="", description="Host identifier") # Port check parameter (only for ports check sub-action) port: int = Field( default=0, ge=0, le=65535, description="Port number to check availability (only for ports check)", ) @computed_field(return_type=list[str]) @property def selected_hosts_list(self) -> list[str]: if not self.selected_hosts: return [] return [h.strip() for h in self.selected_hosts.split(",") if h.strip()] @field_validator("action", mode="before") @classmethod def validate_action(cls, v): """Validate action field to handle various enum input formats.""" return _validate_enum_action(v, HostAction) class DockerContainerParams(MCPModel): """Parameters for the docker_container consolidated tool.""" action: ContainerAction = Field(..., description="Action to perform") container_id: str = Field(default="", description="Container identifier") image_name: str = Field(default="", description="Image name to pull (for pull action)") all_containers: bool = Field( default=False, description="Include all containers (not just running ones)" ) limit: int = Field(default=20, ge=1, le=1000, description="Maximum number of results to return") offset: int = Field(default=0, ge=0, description="Number of results to skip") follow: bool = Field(default=False, description="Follow log output") lines: int = Field(default=100, ge=1, le=10000, description="Number of log lines to retrieve") force: bool = Field(default=False, description="Force the operation") timeout: int = Field(default=10, ge=1, le=300, description="Operation timeout in seconds") host_id: str = Field(default="", description="Host identifier") @field_validator("action", mode="before") @classmethod def validate_action(cls, v): """Validate action field to handle various enum input formats.""" return _validate_enum_action(v, ContainerAction) class DockerComposeParams(MCPModel): """Parameters for the docker_compose consolidated tool.""" action: ComposeAction = Field(..., description="Action to perform") stack_name: DNSName = Field( default="", description="Stack name (DNS-compliant: lowercase letters, numbers, hyphens; no underscores)", ) compose_content: str = Field(default="", description="Docker Compose file content") environment: dict[str, str] = Field(default_factory=dict, description="Environment variables") @field_validator("environment") @classmethod def validate_environment(cls, v): """Validate environment variable keys and values.""" import re if not isinstance(v, dict): return v for key, value in v.items(): # Check for empty keys if not key or key.strip() == "": raise ValueError("Environment variable keys cannot be empty") # Check for None values if value is None: raise ValueError(f"Environment variable '{key}' cannot have None value") # Validate key follows environment variable naming conventions # Must be alphanumeric plus underscore, not starting with digit if not re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", key): raise ValueError(f"Environment variable key '{key}' must contain only letters, numbers, and underscores, and cannot start with a digit") return v pull_images: bool = Field(default=True, description="Pull images before deploying") recreate: bool = Field(default=False, description="Recreate containers") follow: bool = Field(default=False, description="Follow log output") lines: int = Field(default=100, ge=1, le=10000, description="Number of log lines to retrieve") dry_run: bool = Field(description="Perform a dry run without making changes (must be explicitly specified)") options: dict[str, str] | None = Field( default=None, description="Additional options for the operation" ) target_host_id: str = Field(default="", description="Target host ID for migration operations") remove_source: bool = Field(default=False, description="Remove source stack after migration") skip_stop_source: bool = Field( default=False, description="Skip stopping source stack before migration" ) start_target: bool = Field(default=True, description="Start target stack after migration") host_id: str = Field(default="", description="Host identifier") @field_validator("action", mode="before") @classmethod def validate_action(cls, v): """Validate action field to handle various enum input formats.""" return _validate_enum_action(v, ComposeAction)

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/jmagar/docker-mcp'

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