mcp
Qué hace este MCP
Provisions and manages cloud instances, networks, storage, databases, backups, VPNs, application deployments, and autocoding-agent infrastructure.
Herramientas
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'include_managed': {'type': 'boolean', 'description': 'Include managed databases (Postgres/MySQL/MariaDB/ClickHouse/Redis/Qdrant) in the map (default true).'}, 'include_volumes': {'type': 'boolean', 'description': 'Include block volumes in the map (default true).'}, 'include_load_balancers': {'type': 'boolean', 'description': 'Include load balancers in the map (default true).'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'counts': {}, 'resources': {}, 'redu_md_section': {'type': 'string'}, 'report_filename': {'type': 'string'}, 'report_markdown': {'type': 'string'}, 'redu_md_filename': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['volume_id', 'instance_id'], 'properties': {'volume_id': {'type': 'string', 'minLength': 1, 'description': 'Volume to attach/detach — from list_volumes (id). For a recovery, this is the volume restore_backup created (restore_backup with volumeName makes a NEW volume from a backup).'}, 'instance_id': {'type': 'string', 'minLength': 1, 'description': 'Instance to attach it to / detach it from — from list_instances (id).'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'github_pat': {'type': 'string', 'description': 'GitHub Personal Access Token to validate (repo + workflow scopes required)'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'all_ok': {'type': 'boolean'}, 'checks': {}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'enum': ['guided', 'yolo'], 'type': 'string', 'description': "guided = confirm each choice with the user; yolo = auto-proceed with sensible defaults (auto-select the default network, auto-create a keypair). STICKY for the session once set — OMIT it on later re-checks to KEEP the chosen mode (do NOT re-pass 'guided' on a yolo session; passing it flips the session back to guided). Defaults to the session's sticky mode, or guided if never set."}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'quota': {}, 'ready': {'type': 'boolean'}, 'missing': {'type': 'array', 'items': {'type': 'string'}}, 'account_ok': {'type': 'boolean'}, 'network_id': {'type': ['string', 'null']}, 'keypair_name': {'type': ['string', 'null']}, 'platform_facts': {'type': 'array', 'items': {'type': 'string'}}, 'ssh_key_recipe': {'type': 'array', 'items': {'type': 'string'}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'scopes'], 'properties': {'name': {'type': 'string', 'maxLength': 100, 'minLength': 1, 'description': "A recognizable name for the key, e.g. 'supabase-backups'."}, 'scopes': {'type': 'array', 'items': {'type': 'string', 'minLength': 1}, 'minItems': 1, 'description': "LEAST-PRIVILEGE scopes the key may use, e.g. ['instance:read','backup:read','backup:create','backup:restore']. Grant only what the feature needs. Discover the catalog via GET /v1/capabilities (grammar '<resource>:<action>'). billing/subscription/payment/admin are human-only and cannot be granted."}, 'confirm': {'type': 'boolean', 'default': False, 'description': 'Set true ONLY after the user has explicitly approved (see the confirmation the first call returns). Leave unset to get the approval prompt first. Do NOT set it yourself.'}, 'expires_in_days': {'type': 'integer', 'maximum': 365, 'description': 'Optional: auto-expire the key after N days.', 'exclusiveMinimum': 0}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'key': {'type': 'string'}, 'mode': {'type': 'string'}, 'name': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'scopes': {}, 'warning': {'type': 'string'}, 'expires_at': {}, 'validation': {}, 'billing_notice': {'type': 'string'}, 'needs_confirmation': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['backupName'], 'properties': {'volumeId': {'type': 'string', 'minLength': 1, 'description': 'ID of the volume to back up (see list_volumes). Provide this OR instanceId.'}, 'backupName': {'type': 'string', 'minLength': 1, 'description': 'A name for the backup.'}, 'instanceId': {'type': 'string', 'minLength': 1, 'description': 'ID of the instance to back up — its bootable (else first) attached volume is resolved automatically, so no volume:list scope is needed. Provide this OR volumeId.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'flavor_id', 'network_id', 'keypair_name'], 'properties': {'ha': {'type': 'boolean', 'default': False, 'description': "High availability. FALSE (the default) = ONE machine: right for dev, staging and most side projects, but if that machine dies the database is down until it is rebuilt. TRUE = THREE machines on three different physical hosts behind a load balancer, so losing a machine does not lose the database and nobody has to fail it over by hand. COST, say this to the user BEFORE you pass true: three machines instead of one at the size you picked, so roughly 3x the hourly rate of the same non-HA ClickHouse (plus a load balancer). Get an explicit yes on that number: a user who discovers HA from their bill was not asked. ClickHouse gets the easy version of this: all three machines accept reads AND writes, so there is no promotion step and no write pause. A machine dying is dropped from the load balancer, the other two carry on, and its replacement refills itself from them and is only allowed back once it has actually caught up. Queries that were running on the machine that died fail once and need a retry; new queries never see it. ⛔ ONE CONSTRAINT YOU MUST TELL THE USER BEFORE THEY CHOOSE THIS: on three machines every table has to use a REPLICATED engine. `ENGINE = MergeTree` is refused outright (ClickHouse error 56, UNKNOWN_STORAGE) - write `ENGINE = ReplicatedMergeTree` instead, with no arguments. It is refused rather than accepted because a plain MergeTree on three machines replicates its schema and NOT its rows, which would leave two of the three answering the user's queries with an empty table and no error. So anything that ships plain-MergeTree migrations - Plausible, PostHog and Langfuse all do - cannot run on the three-machine version without changing its migrations, and should use the single machine. HA takes longer to provision than a single machine, because the machines are built one at a time on purpose so they land on different hosts. HA is not a backup: it replicates your mistakes too, so keep backups on either setting."}, 'name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Name for the managed ClickHouse database (lowercase letters, numbers, hyphens).'}, 'db_name': {'type': 'string', 'default': 'analytics', 'maxLength': 63, 'minLength': 1, 'description': "The database to create (default 'analytics')."}, 'db_user': {'type': 'string', 'default': 'appuser', 'maxLength': 63, 'minLength': 1, 'description': "The database user (default 'appuser')."}, 'flavor_id': {'type': 'string', 'minLength': 1, 'description': 'Instance size for the ClickHouse VM — from list_flavors. ClickHouse is RAM-hungry; pick m1.small (2GB) or larger.'}, 'superuser': {'type': 'boolean', 'description': 'Grant the db user global rights (CURRENT GRANTS(ALL ON *.*)) on top of its own database - safe here, it is a dedicated single-tenant VM. SET IT for any app whose own MIGRATIONS create ClickHouse objects outside their database, above all USER-DEFINED FUNCTIONS. Measured 2026-08-08: a stock Plausible deploy crash-loops forever on `Code: 497 ... necessary to have the grant CREATE FUNCTION ON *.*` while it creates its 12 acquisition_channel functions, and no amount of retrying fixes it - the database has to be created with this flag. PostHog and other analytics apps that ship SQL UDFs are the same shape. Without it the app deploys, the container restarts, and the only symptom is a migration stack trace.'}, 'network_id': {'type': 'string', 'minLength': 1, 'description': 'Private network id — from list_private_networks. The DB is reachable only from this network.'}, 'db_password': {'type': 'string', 'maxLength': 128, 'minLength': 8, 'description': 'Password for the db user (letters/numbers/_/- only). Auto-generated and returned once if omitted.'}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'SSH keypair name — from list_keypairs.'}, 'idempotency_key': {'type': 'string', 'minLength': 8}, 'security_group_names': {'type': 'array', 'items': {'type': 'string'}, 'default': ['default']}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['github_pat', 'repo'], 'properties': {'repo': {'type': 'string', 'minLength': 1, 'description': "GitHub repo to run agents on, e.g. 'owner/repo'"}, 'github_pat': {'type': 'string', 'minLength': 1, 'description': 'GitHub Personal Access Token (repo + workflow scopes)'}, 'worker_count': {'type': 'integer', 'default': 3, 'maximum': 5, 'minimum': 1, 'description': 'Number of worker VMs to provision (default 3)'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'dns': {'type': 'string'}, 'mode': {'type': 'string'}, 'next': {'type': 'array', 'items': {}}, 'status': {'type': 'string'}, 'ssh_user': {'type': 'string'}, 'log_token': {'type': 'string'}, 'instance_id': {'type': 'string'}, 'ssh_key_name': {'type': 'string'}, 'trigger_token': {'type': 'string'}, 'controller_host': {'type': 'string'}, 'ssh_private_key': {'type': 'string'}, 'authorize_command': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'flavor_id', 'network_id', 'keypair_name'], 'properties': {'ha': {'type': 'boolean', 'default': False, 'description': "High availability. FALSE (the default) = ONE machine: right for dev, staging and most side projects, but if that machine dies the database is down until it is rebuilt. TRUE = THREE machines on three different physical hosts behind a load balancer, so losing a machine does not lose the database and nobody has to fail it over by hand. COST, say this to the user BEFORE you pass true: three machines instead of one at the size you picked, so roughly 3x the hourly rate of the same non-HA Postgres (plus a load balancer). Get an explicit yes on that number: a user who discovers HA from their bill was not asked. What it does and does NOT do for Postgres, state this honestly: only one of the three machines takes writes, so losing either of the other two changes nothing at all, and reads keep working through any single loss. Losing the WRITE machine pauses writes for roughly 30 seconds while one of the others is promoted, and transactions that were open at that moment fail and have to be retried by the app. That is true of every Postgres HA setup, hosted or not, so never promise zero downtime. Say 'no lost writes, one pause of about half a minute'. HA takes longer to provision than a single machine, because the machines are built one at a time on purpose so they land on different hosts. HA is not a backup: it replicates your mistakes too, so keep backups on either setting."}, 'name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Name for the managed database (lowercase letters, numbers, hyphens).'}, 'db_name': {'type': 'string', 'default': 'app', 'maxLength': 63, 'minLength': 1, 'description': "The database to create (default 'app')."}, 'db_user': {'type': 'string', 'default': 'appuser', 'maxLength': 63, 'minLength': 1, 'description': "The database user (default 'appuser')."}, 'version': {'enum': ['16', '15', '14'], 'type': 'string', 'default': '16', 'description': 'Postgres major version (default 16).'}, 'flavor_id': {'type': 'string', 'minLength': 1, 'description': 'Instance size for the DB VM — from list_flavors.'}, 'superuser': {'type': 'boolean', 'description': "Grant the db user SUPERUSER — safe here (a dedicated single-tenant DB VM). Use when the app's own migrations must CREATE EXTENSION or alter roles."}, 'extensions': {'type': 'array', 'items': {'enum': ['vector', 'pgvector', 'postgis', 'pgaudit', 'pg_stat_statements', 'hstore', 'pg_trgm', 'uuid-ossp', 'citext', 'pgcrypto', 'ltree', 'btree_gin', 'btree_gist'], 'type': 'string'}, 'description': "Postgres extensions to pre-install at provision time (allowlisted): 'pgvector'/'vector' (embeddings), 'postgis' (geo), 'pgaudit', 'pg_trgm', 'pgcrypto', 'hstore', 'uuid-ossp', 'citext', 'ltree', 'pg_stat_statements', 'btree_gin', 'btree_gist'. Saves SSHing in to run CREATE EXTENSION; needed by apps like langfuse/lantern (pgvector)."}, 'network_id': {'type': 'string', 'minLength': 1, 'description': 'Private network id — from list_private_networks. The DB is reachable only from this network.'}, 'db_password': {'type': 'string', 'maxLength': 128, 'minLength': 8, 'description': 'Password for the db user. Auto-generated and returned once if omitted.'}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'SSH keypair name — from list_keypairs (for operating the DB VM).'}, 'idempotency_key': {'type': 'string', 'minLength': 8}, 'security_group_names': {'type': 'array', 'items': {'type': 'string'}, 'default': ['default']}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'image_id', 'flavor_id', 'keypair_name', 'network_id'], 'properties': {'name': {'type': 'string', 'minLength': 1}, 'port': {'type': 'integer', 'default': 3000, 'maximum': 65535, 'minimum': 1}, 'dname': {'type': 'string', 'default': ''}, 'volume': {'type': 'object', 'required': ['name', 'size'], 'properties': {'name': {'type': 'string'}, 'size': {'type': 'number', 'exclusiveMinimum': 0}}, 'additionalProperties': False}, 'image_id': {'type': 'string', 'minLength': 1}, 'flavor_id': {'type': 'string', 'minLength': 1}, 'imageName': {'type': 'string', 'default': ''}, 'user_data': {'type': 'string'}, 'network_id': {'type': 'string', 'minLength': 1}, 'dns_entries': {'type': 'array', 'items': {'type': 'object', 'properties': {'port': {'type': 'integer', 'maximum': 65535, 'minimum': 1, 'description': 'Origin HTTP port on the instance that the redu cloud proxy should forward to.'}, 'dname': {'type': 'string', 'default': '', 'description': 'Optional custom domain; leave empty to generate a redu.cloud DNS name.'}}, 'additionalProperties': False}, 'default': [], 'description': "Public DNS/proxy entries to create automatically. Use [{ dname:'', port:8080 }] to generate a redu.cloud URL pointing at an origin process on port 8080."}, 'keypair_name': {'type': 'string', 'minLength': 1}, 'boot_volume_id': {'type': 'string', 'format': 'uuid', 'description': "DISASTER RECOVERY: boot this new VM from an EXISTING volume (one restore_backup just created) instead of a fresh image, so the machine comes back with the restored filesystem AS its root disk. The volume must be 'available' (detached) and bootable. image_id is ignored when this is set. Without it, a restored disk can only be attached as a SECOND device and the VM still boots off a blank root disk."}, 'idempotency_key': {'type': 'string', 'minLength': 8}, 'cloud_init_template': {'enum': ['reduos'], 'type': 'string'}, 'security_group_names': {'type': 'array', 'items': {'type': 'string'}, 'default': ['default']}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'keypair_name'], 'properties': {'name': {'type': 'string', 'pattern': '^[a-z0-9-]+$', 'maxLength': 63, 'minLength': 1, 'description': 'Name for the media space, e.g. myshop-media.'}, 'size_gb': {'type': 'integer', 'default': 20, 'maximum': 2048, 'minimum': 1, 'description': 'Persistent media volume size in GB.'}, 'flavor_id': {'type': 'string', 'default': '2', 'minLength': 1, 'description': 'Small VM flavor id for the NFS media server. m1.small is enough for most WordPress uploads.'}, 'mount_path': {'type': 'string', 'default': '/mnt/redu-media/uploads', 'description': 'Host mount path that app VMs will use before binding into /var/www/html/wp-content/uploads.'}, 'network_id': {'type': 'string', 'minLength': 1, 'description': 'Private network id. Use the same network as the WordPress app and managed DB.'}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'Existing SSH keypair name.'}, 'idempotency_key': {'type': 'string', 'minLength': 8}, 'security_group_names': {'type': 'array', 'items': {'type': 'string'}, 'default': ['default'], 'description': 'Security groups for the media VM. Redu opens NFS 2049 from private networks only.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'flavor_id', 'network_id', 'keypair_name'], 'properties': {'name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Name for the managed Redis instance (lowercase letters, numbers, hyphens).'}, 'version': {'enum': ['7', '6'], 'type': 'string', 'default': '7', 'description': "Redis major version (default '7')."}, 'password': {'type': 'string', 'maxLength': 128, 'minLength': 8, 'description': 'Redis AUTH password (requirepass). Auto-generated and returned once if omitted.'}, 'flavor_id': {'type': 'string', 'minLength': 1, 'description': 'Instance size for the Redis VM — from list_flavors. m1.small (2GB) is plenty for most caches/queues.'}, 'network_id': {'type': 'string', 'minLength': 1, 'description': 'Private network id — from list_private_networks (or check_deploy_prerequisites). Redis is reachable only from this network; use the SAME network as the app that will connect.'}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'SSH keypair name — from list_keypairs (for operating the Redis VM).'}, 'idempotency_key': {'type': 'string', 'minLength': 8}, 'security_group_names': {'type': 'array', 'items': {'type': 'string'}, 'default': ['default']}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'flavor_id', 'network_id', 'keypair_name'], 'properties': {'name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Name for the managed database (lowercase letters, numbers, hyphens).'}, 'engine': {'enum': ['mysql', 'mariadb'], 'type': 'string', 'default': 'mysql', 'description': "Database engine: 'mysql' (default) or 'mariadb'. Both speak the MySQL protocol (mysql:// URL). Pick the one your app/stack uses. (For analytics/column-store needs use create_clickhouse instead — ClickHouse is not a relational DB.)"}, 'db_name': {'type': 'string', 'default': 'app', 'maxLength': 63, 'minLength': 1, 'description': "The database to create (default 'app')."}, 'db_user': {'type': 'string', 'default': 'appuser', 'maxLength': 63, 'minLength': 1, 'description': "The database user (default 'appuser')."}, 'version': {'type': 'string', 'description': "Engine version (e.g. mysql '8.0', mariadb '11.4'). Defaults to the engine's current major if omitted."}, 'flavor_id': {'type': 'string', 'minLength': 1, 'description': 'Instance size for the DB VM — from list_flavors.'}, 'network_id': {'type': 'string', 'minLength': 1, 'description': 'Private network id — from list_private_networks. The DB is reachable only from this network.'}, 'db_password': {'type': 'string', 'maxLength': 128, 'minLength': 8, 'description': 'Password for the db user (letters/numbers/_/- only). Auto-generated and returned once if omitted.'}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'SSH keypair name — from list_keypairs (for operating the DB VM).'}, 'idempotency_key': {'type': 'string', 'minLength': 8}, 'security_group_names': {'type': 'array', 'items': {'type': 'string'}, 'default': ['default']}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['instanceId', 'snapshotName'], 'properties': {'instanceId': {'type': 'string', 'minLength': 1}, 'snapshotName': {'type': 'string', 'minLength': 1}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'size'], 'properties': {'name': {'type': 'string', 'minLength': 1}, 'size': {'type': 'integer', 'maximum': 10000, 'exclusiveMinimum': 0}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'string', 'minLength': 1, 'description': 'ID of the resource to delete.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'string'}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'string', 'minLength': 1, 'description': 'ID of the resource to delete.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'string'}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['stack_name', 'stack_id'], 'properties': {'stack_id': {'type': 'string', 'minLength': 1, 'description': 'Cluster stack id, from list_clusters (id).'}, 'stack_name': {'type': 'string', 'minLength': 1, 'description': 'Cluster stack name, from list_clusters (stack_name).'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}, 'stack_id': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'string', 'minLength': 1, 'description': 'ID of the resource to delete.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'string'}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'integer', 'description': 'Deployment id from list_deployments.', 'exclusiveMinimum': 0}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'number'}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}, 'managed_db': {}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'string', 'minLength': 1, 'description': 'ID of the resource to delete.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'string'}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name'], 'properties': {'name': {'type': 'string', 'minLength': 1, 'description': 'Name of the keypair to delete.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'name': {'type': 'string'}, 'deleted': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'string', 'minLength': 1, 'description': 'ID of the resource to delete.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'string'}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'string', 'minLength': 1, 'description': 'ID of the resource to delete.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'string'}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'string', 'minLength': 1, 'description': 'ID of the resource to delete.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'string'}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'string', 'minLength': 1, 'description': 'ID of the resource to delete.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'string'}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deleted': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'keypair_name'], 'properties': {'env': {'type': 'object', 'description': 'Env vars injected into the container at deploy time (e.g. PGHOST/PGPORT/PGUSER/PGPASSWORD/PGDATABASE from a managed Postgres). Never baked into the image.', 'additionalProperties': {'type': 'string'}}, 'name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Name for the deployment / VM (lowercase letters, numbers, hyphens).'}, 'port': {'type': 'integer', 'default': 3000, 'maximum': 65535, 'minimum': 1, 'description': 'REQUIRED in practice: the port the app actually listens on inside the container — pass the port plan_deploy detected / the Dockerfile EXPOSE / the framework default. redu probes THIS port for health, so a wrong value fails the deploy. Defaults to 3000 only if omitted (e.g. a static nginx app listens on 80 — pass 80). IGNORED when worker:true.'}, 'repo': {'type': 'string', 'format': 'uri', 'description': 'GIT MODE: public git repo URL (https). For a PRIVATE repo also pass git_token. Omit when using source_token (upload mode).'}, 'db_id': {'type': 'integer', 'description': 'Informational link to a managed Postgres (from create_database/list_databases).', 'exclusiveMinimum': 0}, 'dname': {'type': 'string', 'description': "Custom *.redu.cloud subdomain. For a STABLE, KNOWN-AHEAD URL (needed when the app must be told its OWN url — OAuth callbacks, cookie domain, a frontend that calls its API), generate the FULL auto-gen form yourself: `<label>-<8 lowercase letters/digits>.redu.cloud` (e.g. `myapp-7k2m9x4p.redu.cloud`) — that exact form is used VERBATIM — and wire the app's own URL env to that SAME value. A BARE `<label>.redu.cloud` is NOT used as-is: redu appends a random 8-char suffix for uniqueness, so anything wired to the bare name will NOT match the real URL. Omit to auto-generate (then read the real URL from get_deployment)."}, 'redis': {'enum': ['none', 'managed'], 'type': 'string', 'description': "Redis wiring (auto-injects REDIS_URL/REDIS_HOST/REDIS_PORT/REDIS_PASSWORD — zero setup): 'managed' = a SEPARATE managed Redis VM auto-provisioned + wired on the same private network (data persists across app redeploys; reused on a same-name redeploy). Omit (or 'none') for no Redis. With 'managed' you do NOT call create_redis — it's done for you. Use when the app needs Redis (REDIS_URL / bullmq / celery / sidekiq / cache)."}, 'subdir': {'type': 'string', 'description': "Build context within the source (e.g. 'demo-go') when the Containerfile/Dockerfile isn't at the root."}, 'worker': {'type': 'boolean', 'description': 'HEADLESS WORKER / daemon mode. Deploys a long-running container with NO HTTP server, NO public URL, and NO health probe — ready = the container stays running. The VM still gets a floating IP + SSH stream (so you can SSH in), but nothing is exposed on the web. Use for background workers, a chaos-monkey, an on-infra agent runner, cron/queue consumers. `port`, `dname`, and the injected APP_URL/PUBLIC_URL are ignored. Run plan_deploy with worker:true too.'}, 'context': {'type': 'string', 'description': 'Build-context dir within the source (default: repo root, or `subdir`). Set when the Dockerfile lives in a subfolder but builds from the repo root.'}, 'db_name': {'type': 'string', 'description': "DB name for single_vm/managed (default 'app')."}, 'db_user': {'type': 'string', 'description': "DB user for single_vm/managed (default 'appuser')."}, 'git_ref': {'type': 'string', 'description': "git mode only: branch/tag/commit to deploy (default: the repo's default branch)."}, 'runtime': {'type': 'string', 'description': 'Informational: node/python/go/… (e.g. from plan_deploy).'}, 'database': {'enum': ['none', 'single_vm', 'managed'], 'type': 'string', 'description': "DB wiring (auto-injects the connection env + DATABASE_URL — zero setup): 'single_vm' = Postgres ON the app VM (cheapest, data dies when the VM is replaced; Postgres only); 'managed' = a SEPARATE managed-DB VM auto-provisioned + wired on the same private network (data PERSISTS across app redeploys; reused on a same-name redeploy). Omit (or 'none') for no DB. With 'managed' you do NOT call create_database/create_relational_database — it's done for you. Choose the engine with db_engine."}, 'db_engine': {'enum': ['postgres', 'mysql', 'mariadb'], 'type': 'string', 'description': "Managed-DB engine (default 'postgres'). 'mysql'/'mariadb' provision a managed MySQL/MariaDB VM and wire MYSQL_HOST/MYSQL_PORT/MYSQL_USER/MYSQL_PASSWORD/MYSQL_DATABASE + a mysql:// DATABASE_URL — use for WordPress/Matomo/NextCloud/most PHP-LAMP apps. Requires database:'managed' (single_vm is Postgres only)."}, 'flavor_id': {'type': 'string', 'default': '3', 'minLength': 1, 'description': "Instance size — from list_flavors. Default m1.medium (enough RAM to build on the VM). For a RAM-heavy app whose state is in a managed DB (Next.js/cal.com, Rails, JVM), prefer m1.mem16/m1.mem32: full RAM on a lean 40 GB disk, so it's cheaper and snapshots/clusters far faster than the 160 GB m1.xlarge/xlarge-highmem. If you will CLUSTER this app (upgrade_to_cluster), prefer m1.mem16/m1.mem32 regardless of RAM needs — a lean disk makes clustering and every scale-out several times faster (plan_deploy sizes cluster_target onto a mem flavor for you)."}, 'git_token': {'type': 'string', 'description': 'git mode only: token to clone a PRIVATE repo. Omit for public repos.'}, 'db_version': {'type': 'string', 'description': "DB version for single_vm/managed. Postgres: '16'|'15'|'14' (default 16). MySQL: '8.0'. MariaDB: '11.4'|'10.11'. Defaults per engine if omitted."}, 'dockerfile': {'type': 'string', 'description': "Path within the source to the Dockerfile (e.g. 'scripts/Dockerfile') when it's NOT at the root. Pair with `context` when the Dockerfile is in a subfolder but COPYs from the repo root."}, 'network_id': {'type': 'string', 'minLength': 1, 'description': 'Existing private network id — from check_deploy_prerequisites (auto-selects your default) or list_private_networks. Optional: if omitted, redu auto-selects your default network.'}, 'app_profile': {'enum': ['generic', 'wordpress', 'woocommerce'], 'type': 'string', 'description': 'Detected app profile from source inspection. For WordPress/WooCommerce pass wordpress/woocommerce so cluster deploys enforce managed DB + shared media instead of treating local uploads as stateless.'}, 'db_flavor_id': {'type': 'string', 'description': 'managed only: VM size for the dedicated Postgres (from list_flavors). Defaults to the app flavor; m1.small is plenty for most. plan_deploy sizes this for you.'}, 'db_superuser': {'type': 'boolean', 'description': "managed/single_vm Postgres only: grant the app DB user SUPERUSER (dedicated single-tenant DB VM, so safe). Use when the app's migrations create extensions/roles themselves."}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'REQUIRED. An EXISTING SSH keypair name — call list_keypairs and reuse one, or import_keypair first.'}, 'source_token': {'type': 'string', 'minLength': 16, 'description': "UPLOAD MODE: token from prepare_upload's curl step — deploys an uploaded tarball of your LOCAL working dir (no git, no PAT). Use this to deploy uncommitted code, a fixed clone of a repo you don't own, or private code. Omit `repo` when set."}, 'db_extensions': {'type': 'array', 'items': {'enum': ['vector', 'pgvector', 'postgis', 'pgaudit', 'pg_stat_statements', 'hstore', 'pg_trgm', 'uuid-ossp', 'citext', 'pgcrypto', 'ltree', 'btree_gin', 'btree_gist'], 'type': 'string'}, 'description': "managed/single_vm Postgres only: extensions to pre-install (pgvector, postgis, pgaudit, pg_trgm, …). Pass when the app needs one — e.g. langfuse/lantern need pgvector — so you don't have to CREATE EXTENSION by hand."}, 'redis_version': {'enum': ['7', '6'], 'type': 'string', 'description': "managed Redis only: version (default '7')."}, 'cluster_target': {'type': 'boolean', 'description': 'Set TRUE when the user asked to deploy this app as an autoscaling cluster. For WordPress/WooCommerce this makes the backend require managed MySQL/MariaDB plus media_space/central_media_origin before deployment can proceed.'}, 'media_space_id': {'type': 'integer', 'description': 'Existing Redu media space id to mount at WordPress wp-content/uploads. Get it from list_media_spaces.', 'exclusiveMinimum': 0}, 'redis_password': {'type': 'string', 'description': 'managed Redis only: a specific password to set (otherwise auto-generated).'}, 'idempotency_key': {'type': 'string', 'minLength': 8}, 'redis_flavor_id': {'type': 'string', 'description': 'managed Redis only: the dedicated Redis VM size (from list_flavors). Defaults to the app flavor; m1.small is plenty for a cache.'}, 'media_mount_path': {'type': 'string', 'description': 'Host mount path on the app VM/member. Redu mounts this into /var/www/html/wp-content/uploads.'}, 'media_origin_url': {'type': 'string', 'format': 'uri', 'description': 'Public base URL where WordPress wp-content/uploads is served when using central_media_origin. Do not put this on the DB VM.'}, 'media_space_name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Optional media space name when create_media_space:true. Defaults to <deployment-name>-media.'}, 'cluster_media_mode': {'enum': ['local_uploads', 'central_media_origin', 'media_space'], 'type': 'string', 'description': 'Record the WordPress media strategy for future clustering. For real WordPress clusters use media_space by default: Redu mounts a shared uploads filesystem into every member. local_uploads is single-VM only and upgrade_to_cluster will refuse it for WordPress.'}, 'create_media_space': {'type': 'boolean', 'description': 'For WordPress/WooCommerce cluster_target:true: set TRUE when no suitable media space exists. Redu creates an NFS media VM + persistent volume and mounts it into /var/www/html/wp-content/uploads.'}, 'dockerfile_content': {'type': 'string', 'description': 'A Dockerfile to write into the build dir before building — pass the Dockerfile that plan_deploy generated when the repo has none, or to override a broken one. (In upload mode you can instead just include the Dockerfile in the tarball.)'}, 'media_space_size_gb': {'type': 'integer', 'maximum': 2048, 'minimum': 1, 'description': 'Media space data volume size in GB when create_media_space:true (default 20).'}, 'security_group_names': {'type': 'array', 'items': {'type': 'string'}, 'default': ['default']}, 'media_space_flavor_id': {'type': 'string', 'minLength': 1, 'description': 'Flavor id for the media VM when create_media_space:true. Defaults to m1.small/backend default.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'keypair_name'], 'properties': {'env': {'type': 'object', 'description': "Env vars APPENDED to the compose project's .env (for ${VAR} interpolation). We never rewrite your compose file.", 'additionalProperties': {'type': 'string'}}, 'name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Name for the deployment / VM (lowercase letters, numbers, hyphens).'}, 'port': {'type': 'integer', 'default': 8080, 'maximum': 65535, 'minimum': 1, 'description': 'REQUIRED in practice: the HOST port the exposed service publishes (the LEFT side of its compose `ports:` mapping) — redu health-probes + proxies THIS port, so a wrong value fails the deploy. plan_deploy detects it.'}, 'repo': {'type': 'string', 'format': 'uri', 'description': 'GIT MODE: public git repo URL that ships a docker-compose file. Private repo also needs git_token. Omit when using source_token.'}, 'dname': {'type': 'string', 'description': "Custom *.redu.cloud subdomain. For a STABLE, KNOWN-AHEAD URL (needed when the app must be told its OWN url — OAuth callbacks, cookie domain, a frontend that calls its API), generate the FULL auto-gen form yourself: `<label>-<8 lowercase letters/digits>.redu.cloud` (e.g. `myapp-7k2m9x4p.redu.cloud`) — that exact form is used VERBATIM — and wire the app's own URL env to that SAME value. A BARE `<label>.redu.cloud` is NOT used as-is: redu appends a random 8-char suffix for uniqueness, so anything wired to the bare name will NOT match the real URL. Omit to auto-generate (then read the real URL from get_deployment)."}, 'redis': {'enum': ['none', 'managed'], 'type': 'string', 'description': "'managed' = a SEPARATE managed Redis VM, auto-provisioned + wired; its REDIS_URL/REDIS_* is APPENDED to the project .env — your compose service must REFERENCE it to use it (we never rewrite your compose file). Omit/'none' to use the stack's own redis container. With 'managed' you do NOT call create_redis."}, 'expose': {'type': 'array', 'items': {'type': 'object', 'required': ['port'], 'properties': {'port': {'type': 'integer', 'maximum': 65535, 'minimum': 1}, 'dname': {'type': 'string'}, 'service': {'type': 'string'}}, 'additionalProperties': False}, 'description': "MULTI-SURFACE apps: expose several services, each gets its OWN *.redu.cloud URL. The FIRST entry is the primary one redu health-gates (its port overrides `port`). CRITICAL when one surface must KNOW another's URL (a frontend that calls its API — e.g. Lago's front -> API): GENERATE each surface's dname up front as `<label>-<8 lowercase letters/digits>.redu.cloud` (used VERBATIM) and wire the app's cross-surface URL env (LAGO_API_URL, LAGO_FRONT_URL, FRONTEND_URL, NEXT_PUBLIC_API_URL, …) to those EXACT values. Do NOT use a bare `<label>.redu.cloud` — redu appends a random suffix, so config wired to the bare name breaks."}, 'subdir': {'type': 'string', 'description': 'Directory within the source that contains the compose file (if not at the root).'}, 'db_name': {'type': 'string', 'description': "DB name for single_vm/managed (default 'app')."}, 'db_user': {'type': 'string', 'description': "DB user for single_vm/managed (default 'appuser')."}, 'git_ref': {'type': 'string', 'description': "git mode only: branch/tag/commit (default: the repo's default branch)."}, 'service': {'type': 'string', 'description': 'The compose SERVICE to expose at the public URL (informational; the exposed port is `port`).'}, 'database': {'enum': ['compose', 'single_vm', 'managed'], 'type': 'string', 'description': "DB mode: 'compose' (default) = use the compose file's OWN db service (self-contained, nothing extra provisioned); 'single_vm' = Postgres ON the app VM; 'managed' = a SEPARATE managed-PG/MySQL VM. For single_vm/managed the conn env (DATABASE_URL/PG*/MYSQL_*) is APPENDED to the project .env — your compose service must REFERENCE it (e.g. environment: - DATABASE_URL=${DATABASE_URL}) to actually use it; we never modify your compose file. Choose engine with db_engine."}, 'db_engine': {'enum': ['postgres', 'mysql', 'mariadb'], 'type': 'string', 'description': "managed only: 'postgres' (default) → PG* env; 'mysql'/'mariadb' → MYSQL_* env. mysql/mariadb require database:'managed'."}, 'flavor_id': {'type': 'string', 'default': '3', 'minLength': 1, 'description': 'App VM size — from list_flavors. A multi-container stack often wants m1.large+; plan_deploy sizes it.'}, 'git_token': {'type': 'string', 'description': 'git mode only: token to clone a PRIVATE repo.'}, 'db_version': {'type': 'string', 'description': "DB version for single_vm/managed (Postgres '16'|'15'|'14'; MySQL '8.0'; MariaDB '11.4')."}, 'network_id': {'type': 'string', 'minLength': 1, 'description': 'Private network id — auto-selected from check_deploy_prerequisites if omitted.'}, 'app_profile': {'enum': ['generic', 'wordpress', 'woocommerce'], 'type': 'string', 'description': 'Detected app profile from source inspection. For WordPress/WooCommerce pass wordpress/woocommerce so cluster deploys enforce managed DB + shared media instead of treating local uploads as stateless.'}, 'compose_file': {'type': 'string', 'description': "Path within the source to the compose file (e.g. 'deploy/docker-compose.yml'). Auto-detected (docker-compose.yml / compose.yaml / …) if omitted."}, 'db_flavor_id': {'type': 'string', 'description': 'managed only: the dedicated DB VM size (from list_flavors). Defaults to the app flavor.'}, 'db_superuser': {'type': 'boolean', 'description': 'single_vm/managed Postgres: grant the DB user SUPERUSER (dedicated DB VM, so safe).'}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'REQUIRED. An EXISTING SSH keypair name — from list_keypairs / import_keypair.'}, 'source_token': {'type': 'string', 'minLength': 16, 'description': 'UPLOAD MODE: token from prepare_upload — deploys an uploaded tarball of your LOCAL dir (no git). Omit `repo` when set.'}, 'db_extensions': {'type': 'array', 'items': {'enum': ['vector', 'pgvector', 'postgis', 'pgaudit', 'pg_stat_statements', 'hstore', 'pg_trgm', 'uuid-ossp', 'citext', 'pgcrypto', 'ltree', 'btree_gin', 'btree_gist'], 'type': 'string'}, 'description': 'single_vm/managed Postgres: extensions to pre-install (pgvector, postgis, pgaudit, …).'}, 'redis_version': {'enum': ['7', '6'], 'type': 'string', 'description': "managed Redis only: version (default '7')."}, 'cluster_target': {'type': 'boolean', 'description': 'Set TRUE when the user asked to deploy this compose app as an autoscaling cluster. For WordPress/WooCommerce this requires managed MySQL/MariaDB plus media_space/central_media_origin.'}, 'compose_engine': {'enum': ['auto', 'docker', 'podman'], 'type': 'string', 'description': "Container engine for the compose build (default: the server's choice, usually podman). Set 'docker' to force the docker engine."}, 'media_space_id': {'type': 'integer', 'description': 'Existing Redu media space id to mount at WordPress wp-content/uploads. Get it from list_media_spaces.', 'exclusiveMinimum': 0}, 'redis_password': {'type': 'string', 'description': 'managed Redis only: a specific password to set (otherwise auto-generated).'}, 'idempotency_key': {'type': 'string', 'minLength': 8}, 'migrate_command': {'type': 'string', 'description': "One-time DB prepare/migrate/seed, run AFTER `up -d` and BEFORE the app is marked ready — redu runs `podman-compose run --rm <migrate_service|service> <cmd>` (Rails `bundle exec rails db:prepare`, Django `python manage.py migrate`, Prisma `prisma migrate deploy`). REQUIRED for any stack whose schema is NOT auto-created on boot (e.g. Lago): WITHOUT it the stack deploys and flips to 'ready' but 502s on real use because the DB schema is missing."}, 'migrate_service': {'type': 'string', 'description': 'Compose service to run migrate_command in (defaults to `service`).'}, 'redis_flavor_id': {'type': 'string', 'description': 'managed Redis only: the dedicated Redis VM size (from list_flavors). Defaults to the app flavor.'}, 'media_mount_path': {'type': 'string', 'description': 'Host mount path on the app VM/member. Redu mounts this into /var/www/html/wp-content/uploads.'}, 'media_origin_url': {'type': 'string', 'format': 'uri', 'description': 'Public base URL where WordPress wp-content/uploads is served when using central_media_origin. Do not put this on the DB VM.'}, 'media_space_name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Optional media space name when create_media_space:true. Defaults to <deployment-name>-media.'}, 'cluster_media_mode': {'enum': ['local_uploads', 'central_media_origin', 'media_space'], 'type': 'string', 'description': 'Record the WordPress media strategy for future clustering. For real WordPress clusters use media_space by default: Redu mounts a shared uploads filesystem into every member. local_uploads is single-VM only and upgrade_to_cluster will refuse it for WordPress.'}, 'create_media_space': {'type': 'boolean', 'description': 'For WordPress/WooCommerce cluster_target:true: set TRUE when no suitable media space exists. Redu creates an NFS media VM + persistent volume and mounts it into /var/www/html/wp-content/uploads.'}, 'media_space_size_gb': {'type': 'integer', 'maximum': 2048, 'minimum': 1, 'description': 'Media space data volume size in GB when create_media_space:true (default 20).'}, 'security_group_names': {'type': 'array', 'items': {'type': 'string'}, 'default': ['default']}, 'media_space_flavor_id': {'type': 'string', 'minLength': 1, 'description': 'Flavor id for the media VM when create_media_space:true. Defaults to m1.small/backend default.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'flow': {'type': 'array', 'items': {'type': 'string'}}, 'next': {'type': 'string'}, 'tips': {'type': 'array', 'items': {'type': 'string'}}, 'multi_vm': {'type': 'array', 'items': {'type': 'string'}}, 'source_modes': {}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['keypair_name'], 'properties': {'name': {'type': 'string', 'pattern': '^[a-z0-9-]+$', 'maxLength': 48, 'minLength': 1, 'description': "Deployment name (default auto 'vpn-<id>'). Becomes the VM name + the wss://<name>.redu.cloud endpoint."}, 'confirm': {'type': 'boolean', 'default': False, 'description': 'Set true ONLY after the user has explicitly approved (the first call returns the plan + cost). Do NOT set it yourself.'}, 'flavor_id': {'type': 'string', 'default': '2', 'minLength': 1, 'description': "Gateway VM size (from list_flavors). The gateway is light; m1.small ('2') is plenty."}, 'network_id': {'type': 'string', 'minLength': 1, 'description': 'Private network id (from list_networks). Auto-selected from your default private network if omitted — the VMs you want to reach must be on this network.'}, 'client_cidr': {'type': 'string', 'description': "Your tenant PRIVATE-network CIDR (e.g. '10.1.0.0/24') so the client routes it through the tunnel. If omitted, the returned client config only routes the tunnel subnet and you add your CIDR to AllowedIPs yourself."}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'REQUIRED. An EXISTING SSH keypair name (from list_keypairs / import_keypair) for the gateway VM.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'warning': {'type': 'string'}, 'deployment': {}, 'validation': {}, 'access_point': {'type': 'string'}, 'client_config': {'type': 'string'}, 'client_launch': {'type': 'array', 'items': {'type': 'string'}}, 'billing_notice': {'type': 'string'}, 'server_public_key': {'type': 'string'}, 'needs_confirmation': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['volume_id', 'instance_id'], 'properties': {'volume_id': {'type': 'string', 'minLength': 1, 'description': 'Volume to attach/detach — from list_volumes (id). For a recovery, this is the volume restore_backup created (restore_backup with volumeName makes a NEW volume from a backup).'}, 'instance_id': {'type': 'string', 'minLength': 1, 'description': 'Instance to attach it to / detach it from — from list_instances (id).'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['controller_url'], 'properties': {'log_token': {'type': 'string', 'description': 'Log token for fetching controller logs (optional — returned by this tool on first call)'}, 'controller_url': {'type': 'string', 'format': 'uri', 'description': 'HTTPS URL of your controller VM, e.g. https://redu-controller-abc123.redu.cloud'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'status': {}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['deployment_id'], 'properties': {'tail': {'type': 'integer', 'maximum': 1000, 'minimum': 1, 'description': 'Lines per container (default 120). Over 120 asks the VM for a fresh pull, which takes up to ~15s.'}, 'since': {'type': 'string', 'maxLength': 10, 'description': "Only logs newer than this, e.g. '30m', '2h', '7d'. Always triggers a fresh pull from the VM."}, 'service': {'type': 'string', 'maxLength': 200, 'description': 'Container/service name (substring matches). Omit for every container the VM reports. Get exact names from get_containers.'}, 'deployment_id': {'type': 'string', 'minLength': 1, 'description': "A deployment's id, name, or instance_id - all three resolve."}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'hint': {'type': 'string'}, 'logs': {}, 'reason': {'type': 'string'}, 'source': {'type': 'string'}, 'message': {'type': 'string'}, 'measured': {'type': 'boolean'}, 'age_seconds': {'type': 'number'}, 'available_services': {}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['deployment_id'], 'properties': {'deployment_id': {'type': 'string', 'minLength': 1, 'description': "A deployment's id, name, or instance_id - all three resolve."}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'hint': {'type': 'string'}, 'stale': {'type': 'boolean'}, 'engine': {'type': 'string'}, 'reason': {'type': 'string'}, 'message': {'type': 'string'}, 'measured': {'type': 'boolean'}, 'containers': {}, 'deployment': {}, 'age_seconds': {'type': 'number'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'integer', 'description': 'Deployment id from list_deployments.', 'exclusiveMinimum': 0}, 'redu_md': {'type': 'string', 'maxLength': 60000, 'description': "⭐ USUALLY UNNECESSARY NOW: if you POST your current redu.md to the `redu_md_post_url` this tool returns (`curl -fsS --data-binary @redu.md <url>`), redu merges against that and you never paste the file at all - it is 20-29 KB and every byte costs you output. Use this parameter only when you cannot run that command. PASTE the raw contents of the repo's existing `redu.md` if it has one (`cat redu.md`). redu MERGES it server-side - recorded quirks, the pinned dname and the deploy log are carried forward - and returns the COMPLETE new file in redu_md_markdown, which you write out whole. Do NOT merge it yourself. If you OMIT this, redu returns NO redu_md_markdown at all - only redu_md_bootstrap_markdown (for a repo with no redu.md yet) and redu_md_deploy_log_line (to hand-append) - so a forgotten pass can no longer overwrite a repo's accumulated memory. If redu cannot merge what you passed it sets redu_md_merge_blocked and returns NO redu_md_markdown, precisely so there is nothing to overwrite the file with - in that case follow `next` and hand-edit the existing file instead of replacing it."}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'build_log': {'type': ['string', 'null']}, 'deployment': {}, 'report_markdown': {'type': 'string'}, 'failure_analysis': {'anyOf': [{}, {'type': 'null'}]}, 'redu_md_filename': {'type': 'string'}, 'redu_md_markdown': {'type': 'string'}, 'redu_md_post_url': {'type': 'string'}, 'redu_md_merge_lost': {'type': 'array', 'items': {'type': 'string'}}, 'redu_md_merge_mode': {'enum': ['full', 'in_place'], 'type': 'string'}, 'redu_md_merged_url': {'type': 'string'}, 'build_log_truncated': {'type': 'boolean'}, 'build_log_total_lines': {'type': 'number'}, 'redu_md_merge_blocked': {'type': 'boolean'}, 'redu_md_omitted_bytes': {'type': 'number'}, 'redu_md_deploy_log_line': {'type': 'string'}, 'redu_md_last_deploy_block': {'type': 'string'}, 'redu_md_bootstrap_markdown': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['domain'], 'properties': {'domain': {'type': 'string', 'minLength': 1, 'description': 'The custom domain to verify ownership of (e.g. app.example.com).'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['deployment_id'], 'properties': {'deployment_id': {'type': 'string', 'minLength': 1, 'description': "A deployment's id, name, or instance_id - all three resolve."}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'reason': {'type': 'string'}, 'message': {'type': 'string'}, 'measured': {'type': 'boolean'}, 'env_files': {}, 'age_seconds': {'type': 'number'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['instance_id'], 'properties': {'instance_id': {'type': 'string', 'minLength': 1, 'description': 'ID of the instance to fetch BOOT/console logs for. For app logs use get_container_logs instead.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'logs': {}, 'mode': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['deployment_id'], 'properties': {'deployment_id': {'type': 'string', 'minLength': 1, 'description': "A deployment's id, name, or instance_id - all three resolve."}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'host': {}, 'reason': {'type': 'string'}, 'message': {'type': 'string'}, 'measured': {'type': 'boolean'}, 'containers': {}, 'age_seconds': {'type': 'number'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['instance_id'], 'properties': {'instance_id': {'type': 'string', 'minLength': 1, 'description': "An instance id, a deployment's id / name / instance_id, or a managed datastore's id / name / instance_id. All are resolved."}, 'keypair_name': {'type': 'string', 'description': 'The SSH keypair the instance was created with (read it from get_deployment for a deploy VM). When given, the command uses `-i ~/.ssh/<keypair_name>` so it authenticates with the right key.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'host': {'type': 'string'}, 'mode': {'type': 'string'}, 'port': {'type': 'string'}, 'user': {'type': 'string'}, 'floating_ip': {'type': 'string'}, 'ssh_command': {'type': 'string'}, 'keypair_name': {'type': 'string'}, 'instance_name': {'type': 'string'}, 'instance_status': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['name', 'public_key'], 'properties': {'name': {'type': 'string', 'maxLength': 255, 'minLength': 1, 'description': "Name for the keypair (e.g. 'my-laptop'). Must be unique on your account."}, 'public_key': {'type': 'string', 'minLength': 1, 'description': 'SSH public key to import (the contents of your id_rsa.pub or id_ed25519.pub).'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['instanceId', 'action'], 'properties': {'action': {'enum': ['START', 'STOP', 'REBOOT_SOFT', 'REBOOT_HARD'], 'type': 'string'}, 'instanceId': {'type': 'string', 'minLength': 1}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'next': {'type': 'string'}, 'pattern': {'type': 'array', 'items': {'type': 'string'}}, 'recipes': {}, 'scopes_hint': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'backups': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'clickhouse': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'clusters': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'databases': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'deployments': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'dns': {'type': 'array', 'items': {}}, 'mode': {'type': 'string'}, 'next': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'domains': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'flavors': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'images': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'instances': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'keypairs': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'media_spaces': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'networks': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'redis': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'regions': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'relational_databases': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'security_groups': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'snapshots': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'volumes': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['runtime'], 'properties': {'port': {'type': 'integer', 'description': "Port the app's HTTP server listens on (PORT env / framework default / Dockerfile EXPOSE of a real app port — NOT a debug/IPC port). Omit if the repo has no HTTP server.", 'exclusiveMinimum': 0}, 'start': {'type': 'string', 'description': 'How the app starts (package.json start script / Procfile / Dockerfile CMD).'}, 'worker': {'type': 'boolean', 'description': 'HEADLESS WORKER / daemon: the repo runs a long-lived process with NO HTTP server (a chaos-monkey, a background/queue worker, an on-infra agent runner). Set TRUE to plan a WORKER deploy — a private VM with SSH access but NO public URL and NO health probe. serves_http/port are then not required (a serves_http:false repo is NOT rejected). Deploy it with deploy_app worker:true.'}, 'redu_md': {'type': 'string', 'maxLength': 60000, 'description': 'PASTE the raw contents of `redu.md` from the repo root if the file exists (just `cat redu.md`). ⚠️ Only needed when you have NO source_token (a git-mode deploy): with a token, redu reads this file out of your upload and pasting it wastes 20-29 KB of output. You do NOT need to read or interpret it - redu parses it server-side and returns only a short digest. This is how a REDEPLOY keeps the SAME public URL and reuses the recorded fixes instead of rediscovering them.'}, 'runtime': {'type': 'string', 'minLength': 1, 'description': 'Detected app language/runtime (node, python, go, ruby, ...). Informational — the app deploys as a container, so the language does not gate the deploy.'}, 'vm_count': {'type': 'integer', 'default': 1, 'maximum': 10, 'minimum': 1, 'description': 'Number of app VMs (microservices). v1: usually 1.'}, 'db_engine': {'enum': ['postgres', 'mysql', 'mariadb'], 'type': 'string', 'default': 'postgres', 'description': 'Managed DB engine to plan. For WordPress/WooCommerce clusters use mariadb or mysql.'}, 'db_flavor': {'type': 'string', 'default': 'm1.small', 'description': 'Preferred managed Postgres VM size (default m1.small). Resolved against the real flavor list.'}, 'single_vm': {'type': 'boolean', 'default': False, 'description': 'Force everything onto a single VM if the user prefers.'}, 'app_flavor': {'type': 'string', 'default': 'm1.medium', 'description': 'Preferred app VM size (default m1.medium). Resolved against the real flavor list.'}, 'dockerfile': {'type': 'string', 'maxLength': 20000, 'description': "PASTE the raw contents of the repo's Dockerfile if it has one. redu scans it server-side for BuildKit heredocs, empty `EXPOSE ${ARG}`, and source-build fetches (go/cargo/npm/pip/apt) that are known to fail, and returns preemptive fixes."}, 'app_profile': {'enum': ['generic', 'wordpress', 'woocommerce'], 'type': 'string', 'default': 'generic', 'description': 'Detected app profile. Set wordpress/woocommerce when source inspection finds wp-config.php, wp-content, WordPress/WooCommerce packages/plugins, or wordpress/woocommerce compose images. This is used for cluster safety.'}, 'deploy_mode': {'enum': ['guided', 'yolo'], 'type': 'string', 'description': "guided (default) = ONE approval gate: the user approves the plan, then you proceed with the plan's defaults WITHOUT further sub-questions. yolo = auto-proceed end to end without stopping to ask, using sensible defaults. Sticky for the session once set here or via check_deploy_prerequisites."}, 'heavy_build': {'type': 'boolean', 'description': "Set TRUE when the BUILD (not the running app) is resource-heavy — the container is built ON the VM today, so a build that needs more RAM/CPU than the idle app must be sized up or it OOMs mid-build. Signals: compiled-from-source native code (Rust/C++/CGO/Go-from-source), a monorepo/turborepo build, a Node build with a large heap (NODE_OPTIONS=--max-old-space-size), or bundling Chromium. When true, the plan raises the app VM to a build-capable floor (≥ m1.large) so `deploy_app`'s on-VM build doesn't get OOM-killed. The default m1.medium (4 GB) builds light apps fine but OOMs heavy ones."}, 'needs_redis': {'type': 'boolean', 'default': False, 'description': 'App uses Redis (deps redis/ioredis/bullmq/celery or REDIS_URL).'}, 'serves_http': {'type': 'boolean', 'description': "Whether the repo actually RUNS an HTTP server that listens on a port. Set FALSE for a library, CLI tool, or language runtime that has no web server (e.g. a package you `import`, or a `bun`/`node`-style runtime) — redu can only deploy web services, so a non-server repo is reported as not-a-web-service instead of being costed. Note: an `EXPOSE` of a debug/IPC port (Chrome DevTools 9222/9242, metrics) is NOT an HTTP listener — set false. Leave unset only if you're confident it serves HTTP."}, 'compose_yaml': {'type': 'string', 'maxLength': 20000, 'description': "PASTE the raw contents of the repo's docker-compose.yml / compose.yaml if it has one. redu scans it server-side for known deploy-breaking patterns (Docker-only `local` log driver, depends_on:service_healthy, profiles:, image+build, service count) and returns preemptive fixes BEFORE anything is provisioned. Costs you nothing to include; prevents whole classes of first-deploy failure."}, 'memory_heavy': {'type': 'boolean', 'description': "Set TRUE for a RAM-forward RUNNING app whose persistent state lives in a MANAGED DB / external store (NOT on the VM's local disk) — so it needs lots of memory but only a lean disk. Sizes onto a memory-optimized SMALL-DISK flavor (m1.mem16 = 4 vCPU / 16 GB / 40 GB; pass app_flavor:'m1.mem32' for 32 GB): the SAME RAM as the big standard flavors but a 40 GB disk instead of 160 GB — so it costs less AND snapshots/clusters FAR faster (a 40 GB snapshot is ~a third the time of 160 GB), which matters a lot if you'll scale the app into a cluster. Signals: heavy web frameworks (Next.js — e.g. cal.com / cal.diy — Rails, Django), JVM/Java apps, apps running several in-process services, or anything holding large working sets in memory, AND it uses managed Postgres/MySQL (needs_postgres with single_vm:false) or an external DB so the VM disk is just the app image. Do NOT set it if the app stores lots of data on LOCAL disk (user uploads, an on-VM database, large on-disk caches) — that needs a bigger standard-flavor disk. Distinct from heavy_build (BUILD-time RAM); mem16's 16 GB also covers most heavy builds, so the two compose."}, 'source_token': {'type': 'string', 'description': 'The `source_token` returned by your prepare_upload upload. ⚡ PREFER THIS over pasting: redu reads redu.md, the compose file and the Dockerfile straight out of the upload you ALREADY made, so you do not have to emit a 20-29 KB file as tool input. Run prepare_upload FIRST, then pass the token here. The upload is NOT consumed by this: it stays deployable. Anything you also paste below wins over what is read from the upload.'}, 'has_container': {'type': 'boolean', 'default': False, 'description': 'Whether the repo already has a Dockerfile / compose file.'}, 'needs_compose': {'type': 'boolean', 'default': False, 'description': 'Set TRUE when the repo ships a docker-compose.yml / compose.yaml that runs MULTIPLE services (app + its own db/redis/worker containers) as a stack — then deploy with deploy_compose (podman-compose on ONE VM), NOT deploy_app. A single-service compose that just wraps one Dockerfile can still use deploy_app. plan_deploy raises the app VM to a build-capable floor since a multi-container stack needs more RAM.'}, 'cluster_target': {'type': 'boolean', 'default': False, 'description': 'Set TRUE when the user asked to deploy this app as an autoscaling cluster. For WordPress/WooCommerce this requires managed MySQL/MariaDB plus a Redu media space mounted at wp-content/uploads (or an explicitly configured central_media_origin); local uploads are unsafe.'}, 'media_space_id': {'type': 'integer', 'description': 'Existing Redu media space id to reuse for WordPress/WooCommerce cluster uploads. Get it from list_media_spaces. Omit when create_media_space:true.', 'exclusiveMinimum': 0}, 'needs_postgres': {'type': 'boolean', 'default': False, 'description': 'App uses Postgres (deps pg/prisma/sqlalchemy/drizzle or DATABASE_URL).'}, 'containerizable': {'type': 'boolean', 'default': True, 'description': "Whether the app can run in a container. Almost always true (a container is the delivery unit); set false ONLY if the app fundamentally can't be containerized — then redu can't deploy it yet."}, 'needs_vector_db': {'type': 'boolean', 'default': False, 'description': 'App uses a vector DB (deps qdrant-client / langchain+embeddings or QDRANT_URL).'}, 'media_mount_path': {'type': 'string', 'default': '/mnt/redu-media/uploads', 'description': 'Host mount path on app members for the shared uploads filesystem. Redu mounts this into /var/www/html/wp-content/uploads.'}, 'media_origin_url': {'type': 'string', 'format': 'uri', 'description': "Public base URL where WordPress wp-content/uploads is served when cluster_media_mode:'central_media_origin'. Do not use the DB VM as this origin."}, 'needs_clickhouse': {'type': 'boolean', 'default': False, 'description': "App uses ClickHouse: the ANALYTICS / EVENTS store, a separate tier from the app's Postgres/MySQL. Set TRUE on ANY signal: a clickhouse/clickhouse-server image in the compose, a CLICKHOUSE_* / CLICKHOUSE_URL / CH_ env var, a clickhouse client dep (clickhouse-connect, @clickhouse/client, clickhouse-driver, clickhouse-go), or an `ON CLUSTER` / MergeTree migration. Analytics-shaped products (Plausible, PostHog, Langfuse, Matomo, SigNoz) run BOTH a relational DB for config AND ClickHouse for every event, so needs_postgres and needs_clickhouse are usually both true. Leaving it false when the app needs it under-quotes the user by a WHOLE datastore: measured 2026-08-07 on an analytics app, GBP 53.29/mo quoted against GBP 65.99/mo real, because the events tier was simply absent from the plan."}, 'clickhouse_flavor': {'type': 'string', 'default': 'm1.medium', 'description': 'Preferred managed ClickHouse VM size (default m1.medium, a tier above the other datastores, which is what plan_managed_datastore also picks for ClickHouse). Resolved against the real flavor list.'}, 'cluster_media_mode': {'enum': ['local_uploads', 'central_media_origin', 'media_space'], 'type': 'string', 'default': 'local_uploads', 'description': 'For WordPress/WooCommerce cluster_target:true, use media_space as the default real fix: Redu creates/reuses an NFS media VM backed by a volume and mounts it at wp-content/uploads. central_media_origin is only for an already-configured external origin. local_uploads is refused at cluster time.'}, 'create_media_space': {'type': 'boolean', 'default': False, 'description': 'For WordPress/WooCommerce cluster_target:true: set TRUE when no suitable media space exists. The plan will include a small media VM + attached volume and deploy_app/deploy_compose will create it.'}, 'media_space_flavor': {'type': 'string', 'default': 'm1.small', 'description': 'Preferred media VM size when create_media_space:true. Resolved against list_flavors.'}, 'media_space_size_gb': {'type': 'integer', 'default': 20, 'maximum': 2048, 'minimum': 1, 'description': 'Size of the media space data volume in GB when create_media_space:true.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'plan': {}, 'reason': {'type': 'string'}, 'feasible': {'type': 'boolean'}, 'pin_dname': {'type': ['string', 'null']}, 'preflight': {'type': 'array', 'items': {}}, 'deployable': {'type': 'boolean'}, 'memory_used': {'type': 'boolean'}, 'memory_digest': {'type': ['string', 'null']}, 'memory_source': {'type': ['string', 'null']}, 'report_filename': {'type': 'string'}, 'report_markdown': {'type': 'string'}, 'source_files_read': {'anyOf': [{'type': 'array', 'items': {'type': 'string'}}, {'type': 'null'}]}, 'source_files_error': {'type': ['string', 'null']}, 'generated_dockerfile': {'type': ['string', 'null']}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'osHint': {'type': 'string', 'default': ''}, 'sizeHint': {'enum': ['small', 'medium', 'large'], 'type': 'string'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'options': {}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'ha': {'type': 'boolean', 'default': False, 'description': 'Plan a highly available datastore (three machines on three different physical hosts behind a load balancer, surviving the loss of a machine with no manual failover) instead of the default single machine. Set it when the user has said they need to survive a machine failure. It prices at roughly 3x the single-machine hourly rate because it runs three machines, so the plan you show the user must carry that number. Available for postgres and clickhouse; for the other engines the plan comes back single-machine with a note saying so.'}, 'engine': {'enum': ['postgres', 'mysql', 'mariadb', 'redis', 'clickhouse'], 'type': 'string', 'default': 'postgres'}, 'sizeHint': {'enum': ['small', 'medium', 'large'], 'type': 'string'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'notes': {'type': 'array', 'items': {'type': 'string'}}, 'options': {}, 'suggested': {}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'is_git_repo': {'type': 'boolean', 'default': False, 'description': 'If the dir is a git checkout, set true to honor .gitignore (tar only tracked + non-ignored files).'}, 'project_dir': {'type': 'string', 'default': '.', 'description': 'Path to the local app directory to upload (default current dir).'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'next': {'type': 'string'}, 'commands': {'type': 'array', 'items': {'type': 'string'}}, 'endpoint': {'type': 'string'}, 'excludes': {'type': 'array', 'items': {'type': 'string'}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['backupId'], 'properties': {'backupId': {'type': 'string', 'minLength': 1, 'description': 'ID of the backup to restore (see list_backups).'}, 'volumeId': {'type': 'string', 'description': 'Optional: restore into this existing volume.'}, 'instanceId': {'type': 'string', 'description': "Optional: restore into this instance's volume (resolved automatically). The target volume must be available (detached), so stop the instance first."}, 'volumeName': {'type': 'string', 'description': 'Optional: name for a new volume to restore into. Omit volumeId and instanceId to restore into a new volume.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['runtime'], 'properties': {'port': {'type': 'integer', 'default': 3000, 'maximum': 65535, 'minimum': 1, 'description': 'Port the app listens on.'}, 'runtime': {'type': 'string', 'minLength': 1, 'description': 'App runtime (node/python/go/…) — from plan_deploy.'}, 'has_container': {'type': 'boolean', 'default': False, 'description': 'Repo already has a Dockerfile/Containerfile (the compose builds it). If false, write the plan_deploy-generated Dockerfile to ./Dockerfile first.'}, 'needs_postgres': {'type': 'boolean', 'default': False, 'description': 'Include a local Postgres container + wire PG* env.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'next': {'type': 'string'}, 'files': {}, 'caveats': {'type': 'array', 'items': {'type': 'string'}}, 'commands': {'type': 'array', 'items': {'type': 'string'}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['surfaces'], 'properties': {'mode': {'enum': ['guided', 'yolo'], 'type': 'string', 'description': "Drive mode; omit to use the session's sticky mode."}, 'surfaces': {'type': 'array', 'items': {'type': 'object', 'required': ['path', 'kind'], 'properties': {'kind': {'enum': ['browser-desktop', 'web-app', 'static-site', 'api', 'headless-worker', 'docs', 'example', 'library', 'unknown'], 'type': 'string', 'description': "What this surface IS, judged by OPENING its Dockerfile (EXPOSE + CMD/start script) — NOT by the directory name. 'browser-desktop' = a GUI/desktop streamed over noVNC/VNC/KasmVNC/Xvfb (a dir named xfce/kasm/sandbox whose Dockerfile runs noVNC IS this). 'web-app' = a browser app/UI a user uses. 'static-site' = static/marketing. 'api' = backend, no UI. 'headless-worker' = no HTTP UI. 'docs' = documentation. 'example'/'library' = not the product."}, 'path': {'type': 'string', 'description': "Directory of this surface, e.g. 'libs/xfce' or '.' for the repo root."}, 'exposes': {'type': 'array', 'items': {'type': 'integer'}, 'description': 'All ports the Dockerfile EXPOSEs (e.g. [5901,6901]) — pass them so the deploy publishes http_port, not the lowest.'}, 'summary': {'type': 'string', 'description': 'One line: what a user does at this surface.'}, 'http_port': {'type': 'integer', 'maximum': 65535, 'minimum': 1, 'description': 'The port a user opens in the browser for this surface (the web/noVNC port, e.g. 6901 for an xfce noVNC desktop — NOT a raw VNC/debug port).'}, 'needs_external_keys': {'type': 'boolean', 'default': False, 'description': "TRUE if this surface is INERT until the VISITOR supplies their own API key or an external backend/sandbox (e.g. an agent 'playground' that needs an LLM key + a cloud sandbox). Such a surface is heavily demoted vs one that works standalone."}}, 'additionalProperties': False}, 'minItems': 1, 'description': 'EVERY runnable surface you found (run `find . -name Dockerfile -o -name Containerfile`, open each). Be exhaustive — a missed browser-desktop subdir is the #1 cause of a wrong pick.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'chosen': {}, 'ranked': {'type': 'array', 'items': {}}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['stack_id', 'domain'], 'properties': {'domain': {'type': 'string', 'minLength': 1, 'description': 'The hostname to bind. Either your OWN production domain (e.g. shop.acme.com) - which must be verified FIRST, see the tool description - or a .redu.cloud label. A .redu.cloud value is NOT taken literally: it keeps a short-id suffix, so read the bound name from `access_point` in the response instead of assuming you got what you asked for.'}, 'stack_id': {'type': 'string', 'minLength': 1, 'description': "Cluster id, from list_clusters (the row's `id`)."}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'domain': {'type': 'string'}, 'result': {}, 'validation': {}, 'access_point': {'type': 'string'}, 'matched_request': {'type': 'boolean'}, 'requested_domain': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['service', 'id', 'enabled'], 'properties': {'id': {'anyOf': [{'type': 'string', 'minLength': 1}, {'type': 'integer', 'exclusiveMinimum': 0}], 'description': 'Numeric id of the managed service (from list_databases / list_redis / list_relational_databases / etc.).'}, 'enabled': {'type': 'boolean', 'description': 'true = turn ON nightly AUTOMATED backups for this service; false = turn them off.'}, 'service': {'enum': ['postgres', 'mysql', 'mariadb', 'redis', 'qdrant', 'clickhouse'], 'type': 'string', 'description': "Which managed data-service type the id belongs to. A managed Postgres from create_database/list_databases is 'postgres'; MySQL/MariaDB from create_relational_database; plus redis/qdrant/clickhouse."}, 'retention': {'type': 'integer', 'maximum': 90, 'minimum': 1, 'description': 'How many days of nightly backups to keep (optional; keeps the current setting if omitted).'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['github_pat', 'repo'], 'properties': {'repo': {'type': 'string', 'minLength': 1, 'description': "GitHub repo to run agents on, e.g. 'owner/my-app'. Must be accessible with the PAT."}, 'github_pat': {'type': 'string', 'minLength': 1, 'description': 'GitHub Personal Access Token with repo + workflow scopes. Used to clone the repo and open PRs.'}, 'worker_count': {'type': 'integer', 'default': 3, 'maximum': 10, 'minimum': 1, 'description': 'Number of parallel worker VMs (default 3). Each works on a separate task simultaneously.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'repo': {'type': 'string'}, 'fleet_id': {'type': 'string'}, 'ssh_user': {'type': 'string'}, 'log_token': {'type': 'string'}, 'next_steps': {'type': 'array', 'items': {}}, 'worker_ids': {'type': 'array', 'items': {}}, 'instance_id': {'type': 'string'}, 'ssh_key_name': {'type': 'string'}, 'trigger_token': {'type': 'string'}, 'controller_url': {'type': 'string'}, 'controller_host': {'type': 'string'}, 'ssh_private_key': {'type': 'string'}, 'authorize_command': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['github_pat', 'repo'], 'properties': {'repo': {'type': 'string', 'minLength': 1, 'description': "GitHub repo, e.g. 'owner/repo'"}, 'github_pat': {'type': 'string', 'minLength': 1, 'description': 'GitHub Personal Access Token (repo + workflow scopes)'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'repo': {'type': 'string'}, 'ready': {'type': 'boolean'}, 'next_tool': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['controller_url', 'trigger_token'], 'properties': {'trigger_token': {'type': 'string', 'minLength': 1, 'description': 'Trigger token from the controller'}, 'controller_url': {'type': 'string', 'format': 'uri', 'description': 'HTTPS URL of your controller VM'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'ok': {'type': 'boolean'}, 'message': {'type': 'string'}, 'fleet_id': {'type': 'string'}, 'finalize_note': {'type': 'string'}, 'workers_ready': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['stack_name', 'stack_id', 'instance_id'], 'properties': {'stack_id': {'type': 'string', 'minLength': 1, 'description': 'Cluster stack id, from list_clusters (id).'}, 'stack_name': {'type': 'string', 'minLength': 1, 'description': 'Cluster stack name, from list_clusters (stack_name).'}, 'instance_id': {'type': 'string', 'minLength': 1, 'description': "The 'hero' VM to snapshot and roll to every extra member: the source/master VM you upgraded to a cluster and SSH into to make changes. It is your cluster's always-on baseline member. Its CURRENT disk state becomes the new member image, so make your changes on it FIRST, then call this."}, 'idempotency_key': {'type': 'string', 'minLength': 8}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['instance_id', 'name', 'flavor_id', 'network_id', 'keypair_name'], 'properties': {'name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Name for the cluster (lowercase letters, numbers, hyphens).'}, 'port': {'type': 'integer', 'maximum': 65535, 'minimum': 1, 'description': 'Port the app listens on / the load balancer forwards to (default 80). Your source VM must actually serve on this port — the load balancer health-checks it.'}, 'dname': {'type': 'string', 'description': "Optional public DNS name for the cluster's load-balancer access point (a .redu.cloud name is auto-generated if omitted)."}, 'max_size': {'type': 'integer', 'maximum': 10, 'minimum': 1, 'description': 'Peak member count under load (default 5). In the default mode this is EXTRA members added on top of your always-on source VM, and the floor is 0 extra. With high_availability:true the group runs between 3 and this number, so set it >= 3.'}, 'flavor_id': {'type': 'string', 'minLength': 1, 'description': "Member VM size — from list_flavors. Every autoscaling member uses this flavor. STRONGLY prefer m1.mem16/m1.mem32 (memory-optimized, 40 GB disk): clustering snapshots the source disk, so a lean disk makes cluster-create and every scale-out several times faster than a 160 GB standard flavor (and costs less for the same RAM). The member flavor's disk must be >= the source VM's disk, so the biggest win comes from the SOURCE VM being on a mem flavor too — if it is on a big-disk flavor, migrate the app onto a mem-flavor VM before clustering. The user can override with any flavor."}, 'network_id': {'type': 'string', 'minLength': 1, 'description': "Private network id — from list_private_networks. Use the SAME network the app's managed DB / other services are on, so members can reach them by private IP."}, 'app_profile': {'enum': ['generic', 'wordpress', 'woocommerce'], 'type': 'string', 'description': 'Set wordpress/woocommerce when upgrading an older deployment or raw VM that the backend has not profiled. WordPress/WooCommerce clusters require managed MySQL/MariaDB plus a media_space or explicitly configured central_media_origin.'}, 'instance_id': {'type': 'string', 'minLength': 1, 'description': 'The instance to turn into a cluster (from list_instances, or the VM of a deploy_app/deploy_compose deployment). It is snapshotted, and the autoscaling members are booted from that snapshot.'}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'SSH keypair name — from list_keypairs.'}, 'media_space_id': {'type': 'integer', 'description': 'Existing Redu media space id to mount on every WordPress/WooCommerce cluster member.', 'exclusiveMinimum': 0}, 'idempotency_key': {'type': 'string', 'minLength': 8}, 'startup_command': {'type': 'string', 'pattern': '^[^\\n\\r]*$', 'maxLength': 2000, 'description': "Single-line shell command to (re)start the app on each fresh member if the snapshot's own services do not auto-start it. For a podman-compose app: 'cd /opt/app && podman-compose up -d'. Omit to rely on the image's own auto-starting services."}, 'auto_restructure': {'type': 'boolean', 'description': "Instead of just refusing a stateful VM, have redu get its co-located database OFF the VM first, then cluster. FULLY AUTO for a single_vm Postgres (redu deployed it): redu provisions a managed Postgres on the cluster's private network and the members migrate the data + repoint the app on boot — no manual steps (response restructure.mode='auto'). For a compose/unknown DB, ASSISTED: redu provisions the matching managed DB (see restructure_engine) and returns the exact dump/restore/repoint commands to run FROM THE APP VM (response restructure.mode='assisted') — redu will not run an unattended dump against a database it does not own. Only addresses the co-located-DB refusal (cluster_needs_stateless); it does NOT bypass the WordPress media guard. Writes to the OLD VM during the (several-minute) upgrade are not migrated; cut traffic over to the cluster URL once it is up."}, 'media_mount_path': {'type': 'string', 'description': 'Host mount path on cluster members. Redu mounts this into /var/www/html/wp-content/uploads for WordPress/WooCommerce.'}, 'media_origin_url': {'type': 'string', 'format': 'uri', 'description': 'Public base URL where WordPress wp-content/uploads is served from the central media origin. This should be a separate media origin, not the DB VM.'}, 'media_space_name': {'type': 'string', 'maxLength': 63, 'minLength': 1, 'description': 'Optional name for the media space when create_media_space:true. Defaults to <cluster-name>-media.'}, 'confirm_stateless': {'type': 'boolean', 'description': "Override the stateful-VM safety refusal. redu REFUSES to cluster a VM that holds its own data (deployed with database:'single_vm' or a compose 'db' service) - a cluster clones the VM into members, so on-VM data diverges and is lost on scale-in; it returns 409 cluster_needs_stateless + a restructure_plan (move the DB to managed, repoint, redeploy, then cluster). Set true ONLY when the VM is genuinely stateless (state in a managed DB / external store, e.g. database:'managed'), or a raw VM you have made stateless."}, 'high_availability': {'type': 'boolean', 'description': "Set TRUE whenever the user asks for HIGH AVAILABILITY, redundancy, 'no single point of failure', 'survive a host/node failure', or 'stay up if a VM dies'. This is the ONLY way to get an HA cluster and you should pick it yourself when the user's intent is availability rather than load-scaling — do not make them discover it. It runs 3 permanent members spread across 3 DIFFERENT physical hosts; a member that is destroyed is rebuilt AUTOMATICALLY in 1.5 to 5 minutes depending on how it failed (both ends measured), with no action from anyone; updates roll one member at a time, keeping the cluster serving throughout (measured: about 2% of requests blip as each member is swapped, capacity never below 2 of 3, URL unchanged). Trade-off to state in the plan: 3 members run continuously (so 3x the member cost, versus 0 idle members in the default mode), and the source VM leaves the load balancer to become the machine you deploy changes to, so it keeps running and is billed too. Default false = load-scaling mode: the single source VM serves at rest and is NOT auto-replaced if it dies."}, 'cluster_media_mode': {'enum': ['local_uploads', 'central_media_origin', 'media_space'], 'type': 'string', 'description': 'For WordPress/WooCommerce, use media_space as the default real cluster fix. local_uploads is refused because wp-content/uploads would diverge across members.'}, 'create_media_space': {'type': 'boolean', 'description': 'Set TRUE when upgrading a WordPress/WooCommerce deployment that has no media_space_id yet. Redu creates a small NFS media VM + volume, records it, and mounts it on all members.'}, 'restructure_engine': {'enum': ['postgres', 'mysql', 'mariadb'], 'type': 'string', 'description': "For the ASSISTED path (a compose-stack database), which managed engine to provision. WordPress/WooCommerce = 'mysql' (or 'mariadb'). Required when auto_restructure is set and the DB runs inside the compose stack; ignored for a single_vm Postgres (always Postgres)."}, 'scale_in_threshold': {'type': 'number', 'maximum': 1, 'minimum': 0, 'description': 'Average CPU fraction (0-1) below which a member is removed (default 0.2).'}, 'media_space_size_gb': {'type': 'integer', 'maximum': 2048, 'minimum': 1, 'description': 'Media space data volume size in GB when create_media_space:true (default 20).'}, 'scale_out_threshold': {'type': 'number', 'maximum': 1, 'minimum': 0, 'description': 'Average CPU fraction (0-1) above which a member is added (default 0.7).'}, 'media_space_flavor_id': {'type': 'string', 'minLength': 1, 'description': 'Flavor id for the media VM when create_media_space:true. Defaults to the cluster member flavor.'}, 'restructure_db_flavor_id': {'type': 'string', 'description': 'Optional VM size for the provisioned managed database (from list_flavors). Defaults to the member flavor; pick a smaller one (e.g. m1.small) if the DB is light.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}, 'request': {}, 'duplicate': {'type': 'boolean'}, 'plan_tool': {'type': 'string'}, 'needs_plan': {'type': 'boolean'}, 'validation': {}, 'needs_keypair': {'type': 'boolean'}, 'idempotency_key': {'type': 'string'}, 'available_keypairs': {'type': 'array', 'items': {'type': 'string'}}, 'needs_keypair_name': {'type': 'boolean'}, 'invalid_keypair_name': {'type': 'boolean'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['service', 'id'], 'properties': {'id': {'anyOf': [{'type': 'string', 'minLength': 1}, {'type': 'integer', 'exclusiveMinimum': 0}], 'description': "Numeric id of the EXISTING single-machine database (from list_databases / list_clickhouse_databases). It must be status='ready'."}, 'service': {'enum': ['postgres', 'clickhouse'], 'type': 'string', 'description': "Which managed database type the id belongs to. 'postgres' for one from create_database/list_databases; 'clickhouse' for one from create_clickhouse/list_clickhouse_databases. MySQL, MariaDB, Redis and Qdrant have no HA option and this tool cannot make them highly available."}, 'flavor_id': {'type': 'string', 'minLength': 1, 'description': 'Only needed for an old database whose build settings were not recorded; the API says so if it is missing. Otherwise the cluster reuses the machine size the database already has.'}, 'network_id': {'type': 'string', 'minLength': 1, 'description': 'Only needed for an old database whose build settings were not recorded. Otherwise the cluster joins the same private network.'}, 'keypair_name': {'type': 'string', 'minLength': 1, 'description': 'Only needed for an old database whose build settings were not recorded.'}, 'acknowledge_write_loss': {'type': 'boolean', 'default': False, 'description': "REQUIRED, and you must tell the user this in your own words and get a yes BEFORE you set it true. The upgrade copies the data while the old machine is still serving, so anything the application writes to the old machine AFTER the copy starts, and before you repoint the app at the new address, is NOT copied and cannot be recovered afterwards. This was measured on a real upgrade: one row written mid-copy was missing (5001 rows on the old machine, 5000 on the cluster). For a quiet database that is nothing; for one taking live orders it is lost orders. The safe sequence is: pause or drain writes, upgrade, repoint the app at the new address, resume. Never set this true on the user's behalf to be helpful."}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'error': {'type': 'boolean'}, 'result': {}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'integer', 'description': 'Deployment id from list_deployments.', 'exclusiveMinimum': 0}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'id': {'type': 'number'}, 'next': {'type': 'string'}, 'probe': {}, 'status': {'type': 'string'}, 'changed': {'type': 'boolean'}, 'message': {'type': 'string'}, 'ready_at': {'type': 'string'}, 'ready_signal': {'type': 'string'}, 'previous_status': {'type': 'string'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['domain'], 'properties': {'domain': {'type': 'string', 'minLength': 1, 'description': 'The custom domain to verify ownership of (e.g. app.example.com).'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'mode': {'type': 'string'}, 'next': {'type': 'string'}, 'domain': {'type': 'string'}, 'result': {}, 'status': {'type': 'string'}, 'verified_at': {'type': ['string', 'null']}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['id'], 'properties': {'id': {'type': 'integer', 'description': 'Deployment id, from the deploy call or list_deployments.', 'exclusiveMinimum': 0}, 'timeout_s': {'type': 'integer', 'maximum': 600, 'description': 'How long to wait before returning timed_out:true (default 300, max 600). A typical deploy reaches ready in 90 to 250 seconds.', 'exclusiveMinimum': 0}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'next': {'type': 'string'}, 'note': {'type': 'string'}, 'evidence': {}, 'terminal': {'type': 'boolean'}, 'timed_out': {'type': 'boolean'}, 'deployment': {}, 'waited_seconds': {'type': 'number'}}, 'additionalProperties': False}
Esquema de entrada
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {}}
Esquema de salida
{'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'properties': {'next': {'type': 'string'}, 'user': {}, 'quota': {}, 'verified': {'type': 'boolean'}, 'auth_type': {'type': 'string'}}, 'additionalProperties': False}
Cambios recientes en herramientas
Servidores MCP similares
shiply
Publishes and manages web applications with SQL databases, serverless functions, domains, email tests, client intake, contracts, …
Fine Structure
Builds and hosts full-stack applications from prompts and supports agent communication through WhatsApp and email.
EchoRelay
Manages a hosted API relay runtime, including projects, endpoints, credentials, publishing, keys, delivery logs, and dead-letter …
Supero
Builds, validates, publishes, tests, and deploys multi-tenant applications with schemas, CRUD operations, external data connector…
Replicate
Provides access to Replicate models, versions, collections, hardware, predictions, and deployments for running and managing hoste…
Relin
Configures webhook sources and destinations, monitors delivery health, investigates failures, manages retries, and replays events.
Scalix Cloud
Provides managed databases, SQL tools, container builds, persistent Linux machines, domains, scheduled functions, storage, and pr…
RationalBloks
Creates, deploys, manages, and searches schema-based REST API projects and Neo4j knowledge graphs across staging and production e…