Skip to main content
Glama

Deploy an Application

deploy_application
Destructive

Deploy a multi-container application onto Cycle. You supply the app knowledge (image, command, env, ports, volumes, how many members and how they address each other); the tool turns it into a Cycle stack spec, creates and builds the stack, and deploys it into an environment. For a workload that truly needs a full virtual machine use deploy_virtual_machine.

Modes: by default everything deploys through a stack (containers that version and deploy together). One application is ONE call and one stack: every container it needs — data nodes, UI, sidecars — goes in the same 'containers' list. Containers are created stopped, so "incremental" means starting and checking them one at a time afterwards, not deploying them in separate calls; a stack cannot be extended with more containers later. Separate stacks are for independent applications that release on their own. stack:false creates one-off containers directly in the environment with no stack objects. Every rule below applies to both.

Existing stacks: a call with 'containers' ALWAYS creates a new stack. When the user names a stack that already exists — built by this tool, the dashboard, or from a git repo — pass stack_id instead and leave 'containers' out (or pass the original list only to link domains). It deploys the stack's latest usable build into the environment; build_id picks a specific build, rebuild:true generates a fresh build from the stack's source first. Containers the stack already has in that environment are left untouched unless 'redeploy' says to update them — rebuild:true plus redeploy:{reimage:true} is how a new image tag or commit is rolled out to a running deployment. preview:true reports the stack's recent builds, the containers the chosen build creates, and which existing ones would be updated.

MUST GET RIGHT — Cycle accepts these and the application is then silently unreachable or insecure. Preview checks them and an error finding blocks the deploy:

  • Listen on ::. The private network is IPv6-ONLY (discovery serves AAAA records) and the load balancer reaches backends over it, so a process on 0.0.0.0 or localhost is unreachable from siblings and from the LB. IPv4-default apps need IPv6 enabled explicitly (mongod --ipv6, HOST=::), and so do client libraries (Node's ioredis needs ?family=6 on the URL).

  • TLS through the LB needs BOTH "443:" and "80:80" in ports. "443:80" is Cycle notation: LB ingress 443 routes to backend 80 with TLS terminated at the LB.

  • Secrets never go in env or args — both are stored in plain text in the stack. Sequence: deploy (containers are created stopped) → create scoped variables with manage_scoped_variable and source.secret:true → start with cycle_control_container. First boot reads them (postgres initdb reads POSTGRES_PASSWORD once; redis needs its config file present).

  • Stateful containers deploy as a SINGLE instance with their own volume. Model a clustered app as N separate single-instance stateful containers (mongo-0, mongo-1, ...), each with its own volume and unique hostname. Containers reach each other by hostname; the environment must be live for discovery to resolve them.

  • Placement is unconstrained by default — a container may land on ANY server whose pool allows it, so cluster members can spread across providers. Pin hardware with constraints.node.tags.all (every tag present) or .any, and confirm the tag exists with list_servers BEFORE deploying (configure_server sets a server's tags); a tag matching no server leaves the container with no deployment target.

  • public defaults to "disable". Set it only to expose a container.

Images — each container sets exactly ONE of: image (a Docker Hub target like 'mongo:7'; an existing image source with the same origin is reused), image_source (already on Cycle — prefer it whenever the user has one, it carries their registry credentials and build config), or dockerfile (repo or targz_url for Cycle to build). Registry and git credentials are never accepted directly.

Shared file systems — 'shared_file_systems' mounts a shared directory or shared mount a SERVER exposes (by identifier; see list_servers) at a path in the container, read-only or writable; every container that mounts the same identifier shares the files. The identifier must already exist on a server; preview reports which servers expose it, and when none does, offer to add it with configure_server before deploying.

Backups — 'backups' (stateful containers only) has Cycle run 'command' on the cron 'schedule' inside the container and ship its STDOUT to a backup-capable hub integration ('destination', e.g. Backblaze B2); 'restore_command' reads a backup from STDIN. All four are required; the destination must already be enabled on the hub. Commands may reference env vars (mongodump -u $USER) but the tools they call must exist in the image.

Domains — 'domain' exposes a container through the environment load balancer. A DNS zone covering it must already exist; the tool creates a LINKED record pointing at the container and never overwrites an existing one (conflicts are errors to resolve with the user). Forces public:"enable" and requires ports; TLS on the record follows from a '443:' mapping. Cycle creates the environment load balancer only when the environment's services start with a public container present, so after deploying public containers into an environment without one the tool starts the environment's services itself; if that fails the response carries 'load_balancer_missing'.

'application' hint — pass an app name with NO containers to get recommended per-container config, topology, and caveats, then compose the container list from it. Unknown names return the known names instead of an error.

Workflow: 1) call with preview:true — returns the exact spec that would deploy plus checklist findings, and makes NO changes. 2) Confirm with the user, then call again without preview. Never deploy without explicit confirmation.

Asynchronous and RESUMABLE: containers appear only at the last step, so an early empty list_containers means "still working". Every response carries stack/build/job ids, 'phase', and 'recommended_action'. After a transport failure, repeat the call with the same name/deployment_id and follow 'recommended_action' ('wait', 'resume' with stack_id, or 'nothing_to_do'). A stack_id call is idempotent at every phase.

Input Schema

NameRequiredDescriptionDefault
nameNoStack name; also the default container prefix.
stackNoDefault true: deploy via a Cycle stack. false: create or reuse the image source, import the image, and create the container(s) directly in the environment with no stack or build. Preview and domains work the same in both modes.
contextNoWhy are you calling this tool? Briefly describe the user's goal.
previewNoReturn the spec that would deploy plus checklist findings, making NO changes. Always run this first to confirm intent with the user.
rebuildNoWith stack_id: create and generate a fresh build from the stack's source before deploying, even when a live build exists (picks up new image tags or repo commits). Default false reuses the latest build; only a failed or deleted latest build is replaced.
build_idNoWith stack_id: deploy this specific build instead of the latest. A failed or deleted build is rejected.
redeployNoWith stack_id, when the stack's containers already exist in the environment: update them to the chosen build. At least one of reimage/reconfigure must be true. Containers in the build that are missing from the environment are created either way.
stack_idNoDeploy an EXISTING stack (ID, identifier, resource path, or name) into 'environment' instead of creating one — to reuse a stack the user already has, or to continue an interrupted deployment. Picks up from the chosen build's current state (generate, deploy, containers, DNS) without redoing completed steps. 'containers' is optional here and only used to link domains. Not combinable with stack:false.
containersNoThe containers to deploy. Compose these yourself; use the 'application' hint for guidance.
applicationNoOptional app-hint name, free-form. Curated hints: elasticsearch, mongodb, postgres, redis; other names return no hint (not an error). With no 'containers', returns the hint instead of deploying.
environmentYesTarget environment (must already exist).
wait_secondsNoMax seconds this call blocks on the deploy pipeline (default 60). 0 submits the next step and returns immediately. Every response carries stack/build/job ids and 'phase', so a later call with stack_id continues from wherever this one stopped.
checklist_ackNoChecklist error codes from a preview (e.g. 'listener.ipv4-bind') to deploy in spite of. Only after telling the user exactly what the finding says will break; an unacknowledged error blocks the deploy.
deployment_idNoIdempotency key (lowercase slug) used as the stack identifier; defaults to a slug of name. A repeat call with the same key refuses to create a duplicate stack and reports the existing one with the ids needed to resume. Pass a fresh value to deliberately create a separate stack.
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. Changed1 schema field changed
    • addedInput schema / properties / containers / items / properties / shared_file_systems
      Added value: +{
      +  "additionalProperties": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "mount_point": {
      +        "description": "Absolute path inside the container, e.g. '/data/shared'; created if missing.",
      +        "type": "string"
      +      },
      +      "writable": {
      +        "description": "true lets the container write to it; false mounts it read-only.",
      +        "type": "boolean"
      +      }
      +    },
      +    "required": [
      +      "mount_point"
      +    ],
      +    "type": "object"
      +  },
      +  "description": "Shared file systems to mount, keyed by the identifier a server exposes (a shared directory or shared mount; see list_servers). Each entry gives the container mount point and whether it is writable.",
      +  "type": "object"
      +}
  2. Changed1 schema field changed
    • changedInput schema / properties / containers / items / properties / cpu_shares / description
      Previous value: -"CPU limit in shares: 10 = one full thread/vCPU (5 = half, 20 = two). Cycle defaults to 2; omit unless the user asks."New value: +"CPU limit in shares: 10 = one logical CPU (thread); 5 = half, 20 = two. Cycle defaults to 2; omit unless the user asks."
  3. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Far exceeds what the annotations disclose. Annotations only say destructive/non-readOnly/open-world/non-idempotent; the description adds that containers are created stopped, secrets in env/args are stored plaintext, the private network is IPv6-only (silent unreachability), a stack cannot be extended later, preview makes no changes, and the deploy is async/resumable with 'phase' and 'recommended_action'. It also explains the idempotency nuance (a containers call always creates a new stack; a stack_id call is idempotent), which is consistent with idempotentHint=false rather than contradicting it.

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?

Despite its length it is well organized with front-loaded purpose and labeled sections (Modes, Existing stacks, MUST GET RIGHT, Images, Backups, Domains, Workflow, Async). The complexity justifies most of the volume, though some rules (secrets/plaintext, ports TLS notation, backup fields) duplicate what is already covered at 100% schema coverage, which is mild redundancy rather than waste.

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?

For a 15-parameter destructive deploy tool with no output schema, the description supplies the missing operational context: response fields (stack/build/job ids, 'phase', 'recommended_action', 'load_balancer_missing'), checkpoint/resume semantics, and the load-balancer provisioning side effect. An agent can invoke and recover from this tool without opening the schema.

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

Parameters4/5

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

Schema coverage is 100%, so the schema already documents every parameter and the baseline is 3. The description nonetheless adds cross-parameter behavior the schema cannot express: the stack_id path versus a fresh containers call, rebuild+redeploy:{reimage:true} as the image-rollout recipe, preview as the dry run, and deployment_id as the idempotency key. It does not simply restate the schema, so it clears the baseline.

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 multi-container application onto Cycle') and immediately enumerates what the tool does end-to-end: builds a Cycle stack spec, creates and builds the stack, and deploys it into an environment. It explicitly distinguishes itself from the sibling deploy_virtual_machine ('For a workload that truly needs a full virtual machine use deploy_virtual_machine') and differentiates its own stack vs stack:false modes.

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?

Explicit when-to-use routing throughout: stack_id vs containers, rebuild vs build_id vs redeploy, when to use the 'application' hint, and the required preview-then-confirm workflow ('Never deploy without explicit confirmation'). It names the alternatives (deploy_virtual_machine, manage_scoped_variable, configure_server, list_servers, cycle_control_container) and the conditions that select each.

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