Skip to main content
Glama

Deploy a Virtual Machine

deploy_virtual_machine
Destructive

Deploy a virtual machine onto Cycle. Prefer containers (deploy_application) for ordinary workloads; choose a VM only for hard isolation requirements, a custom OS or kernel (custom modules, non-Linux), or legacy software that cannot be containerized.

Platform rules this tool applies or checks:

  • The environment's cluster must contain a hypervisor-capable server. list_servers reports 'virtualization' per server; the response notes when no live server in the cluster confirms it. When hardware has to be provisioned for VMs, get_deployable_server_models reports 'hypervisor' per model (and takes hypervisor_only).

  • Image: exactly one of base_image or image_url. Call with NEITHER to fetch the live base-image catalogue (version identifiers, supported/UEFI flags) without deploying — do that first unless the user named an exact image; prefer versions marked supported. iPXE and external-volume image sources are not exposed here (a 'base' volume backed by a SAN volume is a different thing and IS supported).

  • Resources are explicit: ram is required, plus exactly one of cores or cpu_pin.

  • Storage: volumes MUST include the boot volume, identifier 'base'; creates without one are refused. Other volumes attach as RAW BLOCK DEVICES the guest must partition, format, and mount — remind the user.

  • Access: Cycle generates a root password at create. It is returned here but retrievable for only ~10 minutes, so relay it to the user promptly (afterwards reconfigure_virtual_machine sets a new one). SSH keys attach at provision time: ssh_keys references existing environment-scoped keys, new_ssh_keys creates and attaches them. Serial-over-SSH console access needs no VM networking: get_vm_console_access mints credentials for the user's own interactive session, and run_vm_command runs a single command and returns its output (in-guest setup like partitioning a volume goes through it).

  • Networking follows the container conventions: IPv6-ONLY private network, hostname defaults to the identifier, public defaults to 'disable', ports map like '443:443'. Point a domain at the VM afterwards with manage_dns_record (records can link to VMs).

  • Placement: constraints.node.tags.all/.any restricts which tagged servers may host the VM — same tag model as deploy_application; useful when only some servers are hypervisor-capable.

Workflow:

  1. If the user hasn't picked an image, call with no base_image/image_url to list the base images.

  2. Call with preview:true — returns the exact create request (read-only lookups only; nothing is created) to confirm with the user. Never create without explicit confirmation.

  3. Call again without preview. The VM is created and, unless start:false, started. The first boot downloads the disk image and can outlast wait_seconds; the job keeps running on Cycle (check list_virtual_machines or get_jobs).

Retries are safe: identifier (default: slug of name) is the idempotency key — a repeat call refuses to create a duplicate and reports the existing VM. Pass a fresh identifier to deliberately create another alongside it.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
ramNoRAM limit, e.g. '2G'. At least 512M, less than 65G.
nameNoName for the virtual machine. Required except when listing base images.
coresNoNumber of vCPU cores (1-32).
portsNoPort mappings like '443:443'.
startNoStart the VM right after creation (default). false leaves it stopped for cycle_control_virtual_machine.
publicNoPublic network access. Defaults to 'disable'.
contextNoWhy are you calling this tool? Briefly describe the user's goal.
cpu_pinNoPin the VM to specific host cores/ranges, e.g. '0-3' ('x' = the host's max core).
previewNoReturn the exact create request and make NO changes. Always run this first and confirm with the user.
volumesNoVolumes. Must include the boot volume, e.g. {identifier: 'base', size: '10G'}.
hostnameNoPrivate network hostname. Defaults to the identifier.
ssh_keysNoExisting VM SSH keys to attach, by name or 24-char hex ID. Keys are environment-scoped.
image_urlNoURL of a custom disk image to boot from.
os_flavorNoGuest OS flavor for platform preconfiguration. 'windows' adds virtio-win drivers and mounts a drive of provisioning scripts (github.com/cycleplatform/windows-vm-utils) because Windows lacks cloud-init — tell the user to run them for network setup inside the guest.
base_imageNoCycle base-image VERSION identifier from the catalogue this tool returns when called with no image.
identifierNoIdentifier slug and idempotency key; defaults to a slug of name.
constraintsNoRestrict which tagged servers may host this VM (tags live on servers). Confirm tags with list_servers first.
environmentNoTarget environment (must already exist and be live). Required except when listing base images.
allocate_ramNoPreallocate the RAM instead of growing on demand.
new_ssh_keysNoSSH keys to create in the environment from user-supplied public keys, then attach.
wait_secondsNoMax seconds to wait on the start job (default 60). 0 submits and returns immediately.
allocate_coresNoReserve the cores exclusively for this VM. Only with cores.
conversation_idNoConversation tracking id. Omit on your first tool call; every result then includes a conversation_id line — pass that exact value on all later calls in this conversation.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.9/5.0
Behavior5/5

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

Far exceeds what the annotations (destructiveHint=true, openWorldHint=true, readOnlyHint=false) convey: the ~10-minute root-password retrieval window, the image-download-on-first-boot that can outlast wait_seconds, the fact the job continues on Cycle after return, preview being read-only, and the raw-block-device caveat for non-boot volumes. The only nuance is that the 'retries are safe / identifier is the idempotency key' framing sits in mild tension with idempotentHint=false, but the description explains the mechanism precisely rather than claiming a false behavior.

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?

Given 23 parameters and a multi-step deployment flow, the length is justified and the bullets are front-loaded with the routing decision first. There is minor redundancy — the preview guidance repeats the schema's own preview description, and the workflow restates rules already stated above.

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

Completeness5/5

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

With no output schema, the description still covers what comes back (root password, preview request, job id semantics) and where to check progress (list_virtual_machines, get_jobs). Prerequisites (live environment, hypervisor-capable server, existing SSH keys) and follow-up tools (reconfigure_virtual_machine, manage_dns_record, run_vm_command) are all named.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is 100%, the description adds cross-field rules the schema cannot express: exactly one of base_image or image_url, calling with neither to fetch the image catalogue, ram required plus exactly one of cores or cpu_pin, and the mandatory 'base' boot volume. These constraints materially change how the agent assembles arguments.

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?

States a specific verb and resource ('Deploy a virtual machine onto Cycle') and immediately differentiates from the sibling deploy_application by naming the conditions that select the VM path instead. An agent can route between the two tools without opening either schema.

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

Usage Guidelines5/5

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

Explicitly says when NOT to use it (ordinary workloads → deploy_application) and enumerates the three legitimate use cases (hard isolation, custom OS/kernel, un-containerizable legacy software). The numbered workflow, the 'never create without explicit confirmation' rule, and the pointer to list_servers/get_deployable_server_models for hypervisor capability leave nothing to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources