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; 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.

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

TableJSON 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. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only flag destructive/openWorld/non-idempotent; the description goes far beyond by disclosing that containers are created stopped, that secrets in env/args are stored in plain text, that stateful containers are forced single-instance, that IPv6-only networking and '443:<port>' plus '80:80' are required, and that failures are resumable via stack_id with 'phase'/'recommended_action'. This is exactly the context annotations cannot carry.

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?

Front-loaded and organized under clear headers (MUST GET RIGHT, Images, Backups, Domains, Workflow), so the agent can scan to what it needs. It is nonetheless very long and overlaps substantially with the already-detailed schema, which costs it the top score.

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, nested, destructive, asynchronous tool with no output schema, the description covers everything an agent needs: the preview-then-confirm workflow, resume semantics after transport failure, idempotency key behavior, and named response fields (phase, recommended_action, load_balancer_missing). Nothing material is left to inference.

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 baseline is 3, but the description adds real cross-parameter meaning the schema does not: when to pass stack_id versus containers, that 'containers' always creates a new stack, how rebuild+redeploy:{reimage:true} rolls out a new image, and that domain forces public:'enable'. The schema descriptions are themselves verbose, so the marginal gain is real but not maximal.

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 names what it is not: 'For a workload that truly needs a full virtual machine use deploy_virtual_machine.' The container-vs-VM boundary is drawn explicitly, so an agent can route 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?

Gives explicit when/when-not rules across every branch: new stack vs existing stack_id, stack:false for one-off containers, preview before every real deploy, manage_scoped_variable for secrets, cycle_control_container for starting, list_servers to verify constraint tags. Alternatives are named with the condition that selects them.

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