Skip to main content
Glama
washyu
by washyu

deploy_infrastructure

Deploy infrastructure services like Docker containers, LXD instances, and network configurations to homelab devices based on AI recommendations or user specifications.

Instructions

Deploy new infrastructure based on AI recommendations or user specifications

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
deployment_planYesInfrastructure deployment plan
validate_onlyNoOnly validate the plan without executing

Implementation Reference

  • Tool handler function that processes deploy_infrastructure requests, extracts arguments and calls the core implementation
    async def handle_deploy_infrastructure(arguments: dict[str, Any]) -> dict[str, Any]:
        """Handle deploy_infrastructure tool."""
        result = await deploy_infrastructure_plan(
            deployment_plan=arguments["deployment_plan"],
            validate_only=arguments.get("validate_only", False),
        )
        return {"content": [{"type": "text", "text": result}]}
  • JSON schema definition for deploy_infrastructure tool input, including deployment_plan structure with services and network_changes arrays, plus validate_only option
    "deploy_infrastructure": {
        "description": "Deploy new infrastructure based on AI recommendations or user specifications",
        "inputSchema": {
            "type": "object",
            "properties": {
                "deployment_plan": {
                    "type": "object",
                    "description": "Infrastructure deployment plan",
                    "properties": {
                        "services": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "name": {"type": "string"},
                                    "type": {
                                        "type": "string",
                                        "enum": ["docker", "lxd", "service"],
                                    },
                                    "target_device_id": {"type": "integer"},
                                    "config": {"type": "object"},
                                },
                                "required": ["name", "type", "target_device_id"],
                            },
                        },
                        "network_changes": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "action": {
                                        "type": "string",
                                        "enum": [
                                            "create_vlan",
                                            "configure_firewall",
                                            "setup_routing",
                                        ],
                                    },
                                    "target_device_id": {"type": "integer"},
                                    "config": {"type": "object"},
                                },
                            },
                        },
                    },
                },
                "validate_only": {
                    "type": "boolean",
                    "default": False,
                    "description": "Only validate the plan without executing",
                },
            },
            "required": ["deployment_plan"],
        },
    },
  • Core implementation function that validates deployment plans, optionally executes deployments for Docker/LXD/systemd services and network changes, and returns JSON-formatted results
    async def deploy_infrastructure_plan(deployment_plan: dict[str, Any], validate_only: bool = False) -> str:
        """Deploy new infrastructure based on AI recommendations or user specifications."""
    
        try:
            manager = InfrastructureManager()
    
            # Validate the deployment plan
            validation_result = await _validate_deployment_plan(deployment_plan)
            if not validation_result["valid"]:
                return json.dumps(
                    {
                        "status": "error",
                        "message": f"Deployment plan validation failed: {validation_result['errors']}",
                    }
                )
    
            if validate_only:
                return json.dumps(
                    {
                        "status": "success",
                        "message": "Deployment plan validation passed",
                        "validation_result": validation_result,
                        "estimated_duration": "15-30 minutes",
                        "affected_devices": len(
                            {service.get("target_device_id") for service in deployment_plan.get("services", [])}
                        ),
                    }
                )
    
            # Execute deployment plan
            deployment_results = []
    
            # Deploy services
            for service in deployment_plan.get("services", []):
                result = await _deploy_service(manager, service)
                deployment_results.append(result)
    
            # Apply network changes
            for network_change in deployment_plan.get("network_changes", []):
                result = await _apply_network_change(manager, network_change)
                deployment_results.append(result)
    
            # Update sitemap with new infrastructure
            await _update_sitemap_after_deployment(manager, deployment_results)
    
            successful_deployments = [r for r in deployment_results if r.get("status") == "success"]
            failed_deployments = [r for r in deployment_results if r.get("status") == "error"]
    
            return json.dumps(
                {
                    "status": "success" if len(failed_deployments) == 0 else "partial_success",
                    "message": f"Deployed {len(successful_deployments)} components successfully",
                    "successful_deployments": len(successful_deployments),
                    "failed_deployments": len(failed_deployments),
                    "deployment_results": deployment_results,
                    "next_steps": [
                        "Verify services are running correctly",
                        "Update DNS/load balancer configurations if needed",
                        "Monitor resource usage for optimization opportunities",
                    ],
                },
                indent=2,
            )
    
        except Exception as e:
            return json.dumps(
                {
                    "status": "error",
                    "message": f"Infrastructure deployment failed: {str(e)}",
                }
            )
  • Tool registration mapping the 'deploy_infrastructure' tool name to its handler function in the TOOL_HANDLERS registry
    "deploy_infrastructure": handle_deploy_infrastructure,
  • Helper function that deploys individual services (Docker containers, LXD containers, or systemd services) to target devices via SSH
    async def _deploy_service(manager: InfrastructureManager, service: dict[str, Any]) -> dict[str, Any]:
        """Deploy a single service."""
        try:
            device_id = service["target_device_id"]
            connection_info = await manager.get_device_connection_info(device_id)
            if not connection_info:
                return {
                    "status": "error",
                    "service": service["name"],
                    "error": f"Device {device_id} not found",
                }
    
            async with asyncssh.connect(
                connection_info["hostname"],
                username=connection_info["username"],
                known_hosts=None,
            ) as conn:
                service_type = service["type"]
                service_name = service["name"]
                config = service.get("config", {})
    
                if service_type == "docker":
                    # Deploy Docker container
                    docker_image = config.get("image", "nginx:latest")
                    ports = config.get("ports", [])
                    volumes = config.get("volumes", [])
                    env_vars = config.get("environment", {})
    
                    # Build docker run command
                    cmd_parts = ["docker", "run", "-d", "--name", service_name]
    
                    # Add port mappings
                    for port_mapping in ports:
                        cmd_parts.extend(["-p", port_mapping])
    
                    # Add volume mounts
                    for volume in volumes:
                        cmd_parts.extend(["-v", volume])
    
                    # Add environment variables
                    for key, value in env_vars.items():
                        cmd_parts.extend(["-e", f"{key}={value}"])
    
                    cmd_parts.append(docker_image)
    
                    result = await conn.run(" ".join(cmd_parts))
                    if result.exit_status == 0:
                        stdout_text = (
                            result.stdout.decode()
                            if isinstance(result.stdout, bytes)
                            else str(result.stdout)
                            if result.stdout
                            else ""
                        )
                        return {
                            "status": "success",
                            "service": service_name,
                            "container_id": stdout_text.strip(),
                        }
                    else:
                        return {
                            "status": "error",
                            "service": service_name,
                            "error": result.stderr,
                        }
    
                elif service_type == "lxd":
                    # Deploy LXD container
                    lxd_image = config.get("image", "ubuntu:22.04")
    
                    # Launch LXD container
                    result = await conn.run(f"lxc launch {lxd_image} {service_name}")
                    if result.exit_status == 0:
                        return {
                            "status": "success",
                            "service": service_name,
                            "container": service_name,
                        }
                    else:
                        return {
                            "status": "error",
                            "service": service_name,
                            "error": result.stderr,
                        }
    
                elif service_type == "service":
                    # Deploy systemd service
                    service_file = config.get("service_file", "")
                    if not service_file:
                        return {
                            "status": "error",
                            "service": service_name,
                            "error": "Service file content required",
                        }
    
                    # Write service file
                    await conn.run(f'echo "{service_file}" | sudo tee /etc/systemd/system/{service_name}.service')
                    await conn.run("sudo systemctl daemon-reload")
                    await conn.run(f"sudo systemctl enable {service_name}")
                    result = await conn.run(f"sudo systemctl start {service_name}")
    
                    if result.exit_status == 0:
                        return {
                            "status": "success",
                            "service": service_name,
                            "systemd_service": service_name,
                        }
                    else:
                        return {
                            "status": "error",
                            "service": service_name,
                            "error": result.stderr,
                        }
    
                else:
                    return {
                        "status": "error",
                        "service": service_name,
                        "error": f"Unknown service type: {service_type}",
                    }
    
        except Exception as e:
            return {
                "status": "error",
                "service": service.get("name", "unknown"),
                "error": str(e),
            }
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure but offers minimal information. It states this is a deployment action (implies mutation/write operation) but doesn't mention critical behaviors like: whether this is destructive, what permissions are required, whether changes are reversible, execution time, error handling, or what happens on failure. The description is insufficient for a complex infrastructure deployment tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that gets straight to the point without unnecessary words. It's appropriately sized for a tool with this complexity level, though it could benefit from being more informative given the lack of annotations.

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?

For a complex infrastructure deployment tool with no annotations and no output schema, the description is inadequate. It doesn't explain what 'deploy' actually means operationally, what constitutes successful deployment, what format the deployment plan should follow, or what the tool returns. The description leaves too many critical questions unanswered for safe and effective use.

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 already documents both parameters thoroughly. The description adds no additional parameter semantics beyond mentioning 'AI recommendations or user specifications' which loosely relates to the 'deployment_plan' parameter. This meets the baseline for high schema coverage but doesn't enhance understanding of parameter usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('deploy') and resource ('new infrastructure') with the purpose of implementing AI recommendations or user specifications. It distinguishes from siblings like 'deploy_vm' by being more general infrastructure deployment rather than VM-specific, but doesn't explicitly contrast with other deployment tools.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives like 'deploy_vm', 'install_service', or 'plan_terraform_service'. It mentions 'AI recommendations or user specifications' as input sources but gives no context about appropriate use cases, prerequisites, or exclusions.

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/washyu/mcp_python_server'

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