Help us shape the future of Go! Take the 2026 Go Developer Survey

mcpServer

package
v0.4.74 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AppCommands = []FlyCommand{
	{
		ToolName:        "fly-apps-create",
		ToolDescription: "Create a new Fly.io app.  If you don't specify a name, one will be generated for you.",
		ToolArgs: map[string]FlyArg{
			"name": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"org": {
				Description: "Slug of the organization to create the app in",
				Required:    true,
				Type:        "string",
			},
			"network": {
				Description: "Custom network id",
				Required:    false,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"apps", "create"}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, name)
			} else {
				cmdArgs = append(cmdArgs, "--generate-name")
			}

			if org, ok := args["org"]; ok {
				cmdArgs = append(cmdArgs, "--org", org)
			}

			if network, ok := args["network"]; ok {
				cmdArgs = append(cmdArgs, "--network", network)
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-apps-destroy",
		ToolDescription: "Destroy a Fly.io app.  All machines and volumes will be destroyed.",
		ToolArgs: map[string]FlyArg{
			"name": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"apps", "destroy"}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, name)
			} else {
				return nil, fmt.Errorf("missing required argument: name")
			}

			cmdArgs = append(cmdArgs, "--yes")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-apps-list",
		ToolDescription: "List all Fly.io apps in the organization",
		ToolArgs: map[string]FlyArg{
			"org": {
				Description: "Slug of the organization to list apps for",
				Required:    false,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"apps", "list"}

			if org, ok := args["org"]; ok {
				cmdArgs = append(cmdArgs, "--org", org)
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-apps-move",
		ToolDescription: "Move a Fly.io app to a different organization",
		ToolArgs: map[string]FlyArg{
			"name": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"org": {
				Description: "Slug of the organization to move the app to",
				Required:    true,
				Type:        "string",
			},
			"skip-health-checks": {
				Description: "Skip health checks during the move",
				Required:    false,
				Type:        "boolean",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"apps", "move"}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, name)
			} else {
				return nil, fmt.Errorf("missing required argument: name")
			}

			if org, ok := args["org"]; ok {
				cmdArgs = append(cmdArgs, "--org", org)
			} else {
				return nil, fmt.Errorf("missing required argument: org")
			}

			if skipHealthChecks, ok := args["skip-health-checks"]; ok {
				if value, err := strconv.ParseBool(skipHealthChecks); err == nil && value {
					cmdArgs = append(cmdArgs, "--skip-health-checks")
				}
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-apps-releases",
		ToolDescription: "List all releases for a Fly.io app, including type, when, success/fail and which user triggered the release.",
		ToolArgs: map[string]FlyArg{
			"name": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"apps", "releases"}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, "--app", name)
			} else {
				return nil, fmt.Errorf("missing required argument: name")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-apps-restart",
		ToolDescription: "Restart a Fly.io app. Perform a rolling restart against all running Machines.",
		ToolArgs: map[string]FlyArg{
			"name": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"force-stop": {
				Description: "Force stop the app before restarting",
				Required:    false,
				Type:        "boolean",
			},
			"skip-health-checks": {
				Description: "Skip health checks during the restart",
				Required:    false,
				Type:        "boolean",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"apps", "restart"}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, name)
			} else {
				return nil, fmt.Errorf("missing required argument: name")
			}

			if forceStop, ok := args["force-stop"]; ok {
				if value, err := strconv.ParseBool(forceStop); err == nil && value {
					cmdArgs = append(cmdArgs, "--force-stop")
				}
			}

			if skipHealthChecks, ok := args["skip-health-checks"]; ok {
				if value, err := strconv.ParseBool(skipHealthChecks); err == nil && value {
					cmdArgs = append(cmdArgs, "--skip-health-checks")
				}
			}

			return cmdArgs, nil
		},
	},
}
View Source
var CertsCommands = []FlyCommand{
	{
		ToolName:        "fly-certs-add",
		ToolDescription: "Add an SSL/TLS certificate for a Fly.io app.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"hostname": {
				Description: "The hostname to add a certificate for (e.g. www.example.com)",
				Required:    true,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"certs", "add", "--json"}

			app, ok := args["app"]
			if !ok || app == "" {
				return nil, fmt.Errorf("missing required argument: app")
			}
			cmdArgs = append(cmdArgs, "-a", app)

			hostname, ok := args["hostname"]
			if !ok || hostname == "" {
				return nil, fmt.Errorf("missing required argument: hostname")
			}
			cmdArgs = append(cmdArgs, hostname)

			return cmdArgs, nil
		},
	},
	{
		ToolName:        "fly-certs-check",
		ToolDescription: "Check the status of an SSL/TLS certificate for a Fly.io app.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"hostname": {
				Description: "The hostname to check the certificate for (e.g. www.example.com)",
				Required:    true,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"certs", "check", "--json"}

			app, ok := args["app"]
			if !ok || app == "" {
				return nil, fmt.Errorf("missing required argument: app")
			}
			cmdArgs = append(cmdArgs, "-a", app)

			hostname, ok := args["hostname"]
			if !ok || hostname == "" {
				return nil, fmt.Errorf("missing required argument: hostname")
			}
			cmdArgs = append(cmdArgs, hostname)

			return cmdArgs, nil
		},
	},
	{
		ToolName:        "fly-certs-list",
		ToolDescription: "List all SSL/TLS certificates for a Fly.io app.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"certs", "list", "--json"}

			app, ok := args["app"]
			if !ok || app == "" {
				return nil, fmt.Errorf("missing required argument: app")
			}
			cmdArgs = append(cmdArgs, "-a", app)

			return cmdArgs, nil
		},
	},
	{
		ToolName:        "fly-certs-remove",
		ToolDescription: "Remove an SSL/TLS certificate for a Fly.io app.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"hostname": {
				Description: "The hostname to remove the certificate for (e.g. www.example.com)",
				Required:    true,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"certs", "remove", "--json"}

			app, ok := args["app"]
			if !ok || app == "" {
				return nil, fmt.Errorf("missing required argument: app")
			}
			cmdArgs = append(cmdArgs, "-a", app)

			hostname, ok := args["hostname"]
			if !ok || hostname == "" {
				return nil, fmt.Errorf("missing required argument: hostname")
			}
			cmdArgs = append(cmdArgs, hostname)

			return cmdArgs, nil
		},
	},
	{
		ToolName:        "fly-certs-show",
		ToolDescription: "Show details for an SSL/TLS certificate for a Fly.io app.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"hostname": {
				Description: "The hostname to show the certificate for (e.g. www.example.com)",
				Required:    true,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"certs", "show", "--json"}

			app, ok := args["app"]
			if !ok || app == "" {
				return nil, fmt.Errorf("missing required argument: app")
			}
			cmdArgs = append(cmdArgs, "-a", app)

			hostname, ok := args["hostname"]
			if !ok || hostname == "" {
				return nil, fmt.Errorf("missing required argument: hostname")
			}
			cmdArgs = append(cmdArgs, hostname)

			return cmdArgs, nil
		},
	},
}
View Source
var IPCommands = []FlyCommand{
	{
		ToolName:        "fly-ips-allocate-v4",
		ToolDescription: "Allocate an IPv4 address to the application. Dedicated IPv4 addresses cost $2/mo.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"shared": {
				Description: "Allocate a shared IPv4 address instead of dedicated",
				Required:    false,
				Type:        "boolean",
				Default:     "false",
			},
			"region": {
				Description: "Region to allocate the IP address in",
				Required:    false,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"ips", "allocate-v4"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "--app", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			if shared, ok := args["shared"]; ok {
				if value, err := strconv.ParseBool(shared); err == nil && value {
					cmdArgs = append(cmdArgs, "--shared")
				}
			}

			if region, ok := args["region"]; ok {
				cmdArgs = append(cmdArgs, "--region", region)
			}

			cmdArgs = append(cmdArgs, "--yes")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-ips-allocate-v6",
		ToolDescription: "Allocate an IPv6 address to the application",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"private": {
				Description: "Allocate a private IPv6 address",
				Required:    false,
				Type:        "boolean",
				Default:     "false",
			},
			"region": {
				Description: "Region to allocate the IP address in",
				Required:    false,
				Type:        "string",
			},
			"org": {
				Description: "Organization slug (required for private IPv6)",
				Required:    false,
				Type:        "string",
			},
			"network": {
				Description: "Target network name for a Flycast private IPv6 address",
				Required:    false,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"ips", "allocate-v6"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "--app", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			if private, ok := args["private"]; ok {
				if value, err := strconv.ParseBool(private); err == nil && value {
					cmdArgs = append(cmdArgs, "--private")
				}
			}

			if region, ok := args["region"]; ok {
				cmdArgs = append(cmdArgs, "--region", region)
			}

			if org, ok := args["org"]; ok {
				cmdArgs = append(cmdArgs, "--org", org)
			}

			if network, ok := args["network"]; ok {
				cmdArgs = append(cmdArgs, "--network", network)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-ips-list",
		ToolDescription: "List all IP addresses allocated to the application",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"ips", "list"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "--app", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-ips-release",
		ToolDescription: "Release one or more IP addresses from the application",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"addresses": {
				Description: "IP addresses to release",
				Required:    true,
				Type:        "array",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"ips", "release"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "--app", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			if addresses, ok := args["addresses"]; ok {

				for addr := range strings.SplitSeq(addresses, ",") {
					addr = strings.TrimSpace(addr)
					if addr != "" {
						cmdArgs = append(cmdArgs, addr)
					}
				}
			} else {
				return nil, fmt.Errorf("missing required argument: addresses")
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-ips-private",
		ToolDescription: "List instances' private IP addresses, accessible from within the Fly network",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"ips", "private"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "--app", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},
}
View Source
var LogCommands = []FlyCommand{
	{
		ToolName:        "fly-logs",
		ToolDescription: "Get logs for a Fly.io app or specific machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"machine": {
				Description: "Specific machine ID",
				Required:    false,
				Type:        "string",
			},
			"region": {
				Description: "Region to get logs from",
				Required:    false,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"logs", "--no-tail"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			if machine, ok := args["machine"]; ok {
				cmdArgs = append(cmdArgs, "--machine", machine)
			}

			if region, ok := args["region"]; ok {
				cmdArgs = append(cmdArgs, "--region", region)
			}

			return cmdArgs, nil
		},
	},
}
View Source
var MachineCommands = []FlyCommand{
	{
		ToolName:        "fly-machine-clone",
		ToolDescription: "Clone a Fly Machine. The new Machine will be a copy of the specified Machine. If the original Machine has a volume, then a new empty volume will be created and attached to the new Machine.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to clone",
				Required:    true,
				Type:        "string",
			},
			"attach-volume": {
				Description: "Attach a volume to the new machine",
				Required:    false,
				Type:        "string",
			},
			"clear-auto-destroy": {
				Description: "Disable auto destroy setting on the new Machine",
				Required:    false,
				Type:        "boolean",
			},
			"clear-cmd": {
				Description: "Set empty CMD on the new Machine so it uses default CMD for the image",
				Required:    false,
				Type:        "boolean",
			},
			"from-snapshot": {
				Description: "Clone attached volumes and restore from snapshot, use 'last' for most recent snapshot. The default is an empty volume.",
				Required:    false,
				Type:        "string",
			},
			"host-dedication-id": {
				Description: "The dedication id of the reserved hosts for your organization (if any)",
				Required:    false,
				Type:        "string",
			},
			"name": {
				Description: "Optional name of the new machine",
				Required:    false,
				Type:        "string",
			},
			"override-cmd": {
				Description: "Set CMD on the new Machine to this value",
				Required:    false,
				Type:        "string",
			},
			"region": {
				Description: "Region to create the new machine in",
				Required:    false,
				Type:        "string",
			},
			"standby-for": {
				Description: "Standby for a machine in the same region",
				Required:    false,
				Type:        "array",
			},
			"vm-cpu-kind": {
				Description: "The CPU kind to use for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"shared", "dedicated"},
			},
			"vm-cpus": {
				Description: "The number of CPUs to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-gpu-kind": {
				Description: "If set, the GPU model to attach",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"a100-pcie-40gb", "a100-sxm4-80gb", "l40s", "a10", "none"},
			},
			"vm-gpus": {
				Description: "The number of GPUs to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-memory": {
				Description: "The amount of memory (in megabytes) to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-size": {
				Description: `The VM size to set machines to. See "fly platform vm-sizes" for valid values`,
				Required:    false,
				Type:        "string",
			},
			"volume-requires-unique-zone": {
				Description: "Require volume to be placed in separate hardware zone from existing volumes.",
				Required:    false,
				Type:        "boolean",
				Default:     "true",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "clone"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			if attachVolume, ok := args["attach-volume"]; ok {
				cmdArgs = append(cmdArgs, "--attach-volume", attachVolume)
			}

			if clearAutoDestroy, ok := args["clear-auto-destroy"]; ok {
				value, err := strconv.ParseBool(clearAutoDestroy)
				if err != nil {
					return nil, fmt.Errorf("invalid value for clear-auto-destroy: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--clear-auto-destroy")
				}
			}

			if clearCmd, ok := args["clear-cmd"]; ok {
				value, err := strconv.ParseBool(clearCmd)
				if err != nil {
					return nil, fmt.Errorf("invalid value for clear-cmd: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--clear-cmd")
				}
			}

			if fromSnapshot, ok := args["from-snapshot"]; ok {
				cmdArgs = append(cmdArgs, "--from-snapshot", fromSnapshot)
			}

			if hostDedicationID, ok := args["host-dedication-id"]; ok {
				cmdArgs = append(cmdArgs, "--host-dedication-id", hostDedicationID)
			}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, "--name", name)
			}

			if overrideCmd, ok := args["override-cmd"]; ok {
				cmdArgs = append(cmdArgs, "--override-cmd", overrideCmd)
			}

			if region, ok := args["region"]; ok {
				cmdArgs = append(cmdArgs, "--region", region)
			}

			if standbyFor, ok := args["standby-for"]; ok {
				cmdArgs = append(cmdArgs, "--standby-for", standbyFor)
			}

			if vmCpuKind, ok := args["vm-cpu-kind"]; ok {
				cmdArgs = append(cmdArgs, "--vm-cpu-kind", vmCpuKind)
			}

			if vmCpus, ok := args["vm-cpus"]; ok {
				cmdArgs = append(cmdArgs, "--vm-cpus", vmCpus)
			}

			if vmGpuKind, ok := args["vm-gpu-kind"]; ok {
				cmdArgs = append(cmdArgs, "--vm-gpu-kind", vmGpuKind)
			}

			if vmGpus, ok := args["vm-gpus"]; ok {
				cmdArgs = append(cmdArgs, "--vm-gpus", vmGpus)
			}

			if vmMemory, ok := args["vm-memory"]; ok {
				cmdArgs = append(cmdArgs, "--vm-memory", vmMemory)
			}

			if vmSize, ok := args["vm-size"]; ok {
				cmdArgs = append(cmdArgs, "--vm-size", vmSize)
			}

			if volumeRequiresUniqueZone, ok := args["volume-requires-unique-zone"]; ok {
				value, err := strconv.ParseBool(volumeRequiresUniqueZone)
				if err != nil {
					return nil, fmt.Errorf("invalid value for volume-requires-unique-zone: %v", err)
				} else if !value {
					cmdArgs = append(cmdArgs, "--volume-requires-unique-zone=false")
				}
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-cordon",
		ToolDescription: "Deactivate all services on a machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to cordon",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "cordon"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			cmdArgs = append(cmdArgs, "--verbose")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-create",
		ToolDescription: "Create, but don’t start, a machine",
		ToolArgs: map[string]FlyArg{

			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"autostart": {
				Description: "Automatically start a stopped Machine when a network request is received",
				Required:    false,
				Type:        "boolean",
				Default:     "true",
			},
			"autostop": {
				Description: "Automatically stop a Machine when there are no network requests for it",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"off", "stop", "suspend"},
				Default:     "off",
			},
			"entrypoint": {
				Description: "The command to override the Docker ENTRYPOINT",
				Required:    false,
				Type:        "string",
			},
			"env": {
				Description: "Set of environment variables in the form of NAME=VALUE pairs.",
				Required:    false,
				Type:        "array",
			},
			"host-dedication-id": {
				Description: "The dedication id of the reserved hosts for your organization (if any)",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "Machine ID, if previously known",
				Required:    false,
				Type:        "string",
			},
			"image": {
				Description: "The image to use for the new machine",
				Required:    true,
				Type:        "string",
			},
			"metadata": {
				Description: "Set of metadata in the form of NAME=VALUE pairs.",
				Required:    false,
				Type:        "array",
			},
			"name": {
				Description: "Name of the new machine. Will be generated if omitted.",
				Required:    false,
				Type:        "string",
			},
			"port": {
				Description: "The external ports and handlers for services, in the format: port[:machinePort][/protocol[:handler[:handler...]]])",
				Required:    false,
				Type:        "array",
			},
			"region": {
				Description: "Region to create the new machine in",
				Required:    false,
				Type:        "string",
			},
			"restart": {
				Description: "Restart policy for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"no", "always", "on-failure"},
			},
			"rm": {
				Description: "Automatically remove the Machine when it exits",
				Required:    false,
				Type:        "boolean",
			},
			"schedule": {
				Description: "Schedule for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"hourly", "daily", "weekly", "monthly"},
			},
			"skip-dns-registration": {
				Description: "Skip DNS registration for the new machine",
				Required:    false,
				Type:        "boolean",
			},
			"standby-for": {
				Description: "For Machines without services, a comma separated list of Machine IDs to act as standby for.",
				Required:    false,
				Type:        "array",
			},
			"use-zstd": {
				Description: "Use zstd compression for the image",
				Required:    false,
				Type:        "boolean",
			},
			"vm-cpu-kind": {
				Description: "The CPU kind to use for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"shared", "dedicated"},
			},
			"vm-cpus": {
				Description: "The number of CPUs to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-gpu-kind": {
				Description: "If set, the GPU model to attach",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"a100-pcie-40gb", "a100-sxm4-80gb", "l40s", "a10", "none"},
			},
			"vm-gpus": {
				Description: "The number of GPUs to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-memory": {
				Description: "The amount of memory (in megabytes) to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-size": {
				Description: `The VM size to set machines to. See "fly platform vm-sizes" for valid values`,
				Required:    false,
				Type:        "string",
			},
			"volume": {
				Description: "Volume to mount, in the form of <volume_id_or_name>:/path/inside/machine[:<options>]",
				Required:    false,
				Type:        "array",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "create"}

			if image, ok := args["image"]; ok {
				cmdArgs = append(cmdArgs, image)
			} else {
				return nil, fmt.Errorf("missing required argument: image")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			if autostart, ok := args["autostart"]; ok {
				value, err := strconv.ParseBool(autostart)
				if err != nil {
					return nil, fmt.Errorf("invalid value for autostart: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--autostart")
				}
			}

			if autostop, ok := args["autostop"]; ok {
				cmdArgs = append(cmdArgs, "--autostop", autostop)
			}

			if entrypoint, ok := args["entrypoint"]; ok {
				cmdArgs = append(cmdArgs, "--entrypoint", entrypoint)
			}

			if env, ok := args["env"]; ok {
				cmdArgs = append(cmdArgs, "--env", env)
			}

			if hostDedicationID, ok := args["host-dedication-id"]; ok {
				cmdArgs = append(cmdArgs, "--host-dedication-id", hostDedicationID)
			}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, "--id", id)
			}

			if metadata, ok := args["metadata"]; ok {
				cmdArgs = append(cmdArgs, "--metadata", metadata)
			}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, "--name", name)
			}

			if port, ok := args["port"]; ok {
				cmdArgs = append(cmdArgs, "--port", port)
			}

			if region, ok := args["region"]; ok {
				cmdArgs = append(cmdArgs, "--region", region)
			}

			if restart, ok := args["restart"]; ok {
				cmdArgs = append(cmdArgs, "--restart", restart)
			}

			if rm, ok := args["rm"]; ok {
				value, err := strconv.ParseBool(rm)
				if err != nil {
					return nil, fmt.Errorf("invalid value for rm: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--rm")
				}
			}

			if schedule, ok := args["schedule"]; ok {
				cmdArgs = append(cmdArgs, "--schedule", schedule)
			}

			if skipDnsRegistration, ok := args["skip-dns-registration"]; ok {
				value, err := strconv.ParseBool(skipDnsRegistration)
				if err != nil {
					return nil, fmt.Errorf("invalid value for skip-dns-registration: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--skip-dns-registration")
				}
			}

			if standbyFor, ok := args["standby-for"]; ok {
				cmdArgs = append(cmdArgs, "--standby-for", standbyFor)
			}

			if useZstd, ok := args["use-zstd"]; ok {
				value, err := strconv.ParseBool(useZstd)
				if err != nil {
					return nil, fmt.Errorf("invalid value for use-zstd: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--use-zstd")
				}
			}

			if vmCpuKind, ok := args["vm-cpu-kind"]; ok {
				cmdArgs = append(cmdArgs, "--vm-cpu-kind", vmCpuKind)
			}

			if vmCpus, ok := args["vm-cpus"]; ok {
				cmdArgs = append(cmdArgs, "--vm-cpus", vmCpus)
			}

			if vmGpuKind, ok := args["vm-gpu-kind"]; ok {
				cmdArgs = append(cmdArgs, "--vm-gpu-kind", vmGpuKind)
			}

			if vmGpus, ok := args["vm-gpus"]; ok {
				cmdArgs = append(cmdArgs, "--vm-gpus", vmGpus)
			}

			if vmMemory, ok := args["vm-memory"]; ok {
				cmdArgs = append(cmdArgs, "--vm-memory", vmMemory)
			}

			if vmSize, ok := args["vm-size"]; ok {
				cmdArgs = append(cmdArgs, "--vm-size", vmSize)
			}

			if volume, ok := args["volume"]; ok {
				cmdArgs = append(cmdArgs, "--volume", volume)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-destroy",
		ToolDescription: "Destroy one or more Fly machines. This command requires a machine to be in a stopped or suspended state unless the force flag is used.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to destroy",
				Required:    true,
				Type:        "string",
			},
			"force": {
				Description: "Force destroy the machine, even if it is running",
				Required:    false,
				Type:        "boolean",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "destroy"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			if force, ok := args["force"]; ok {
				value, err := strconv.ParseBool(force)
				if err != nil {
					return nil, fmt.Errorf("invalid value for force: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--force")
				}
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-egress-ip-allocate",
		ToolDescription: "Allocate a pair of static egress IPv4 and IPv6 for a machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to allocate egress IP for",
				Required:    true,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "egress-ip", "allocate"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			cmdArgs = append(cmdArgs, "--yes")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-egress-ip-list",
		ToolDescription: "List all static egress IPv4 and IPv6 for a machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to list egress IP for",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "egress-ip", "list"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			cmdArgs = append(cmdArgs, "--verbose")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-egress-ip-release",
		ToolDescription: "Release a pair of static egress IPv4 and IPv6 for a machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to release egress IP for",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "egress-ip", "release"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			cmdArgs = append(cmdArgs, "--yes")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-exec",
		ToolDescription: "Run a command on a machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to run the command on",
				Required:    true,
				Type:        "string",
			},
			"command": {
				Description: "Command to run on the machine",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "exec"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if command, ok := args["command"]; ok {
				cmdArgs = append(cmdArgs, command)
			} else {
				return nil, fmt.Errorf("missing required argument: command")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-leases-clear",
		ToolDescription: "Clear the leases for a machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to clear leases for",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "leases", "clear"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-kill",
		ToolDescription: "Kill (SIGKILL) a Fly machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to kill",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "kill"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-leases-view",
		ToolDescription: "View machine leases",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to list leases for",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "leases", "view"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-list",
		ToolDescription: "List all machines for a Fly app",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "list"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-restart",
		ToolDescription: "Restart a Fly machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to restart",
				Required:    true,
				Type:        "string",
			},
			"force": {
				Description: "Force stop if it is running",
				Required:    false,
				Type:        "boolean",
			},
			"signal": {
				Description: "Signal to send to the machine",
				Required:    false,
				Type:        "string",
			},
			"skip-health-checks": {
				Description: "Skip health checks during the restart",
				Required:    false,
				Type:        "boolean",
			},
			"time": {
				Description: "Seconds to wait before killing the machine",
				Required:    false,
				Type:        "number",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "restart"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			if force, ok := args["force"]; ok {
				value, err := strconv.ParseBool(force)
				if err != nil {
					return nil, fmt.Errorf("invalid value for force: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--force")
				}
			}

			if signal, ok := args["signal"]; ok {
				cmdArgs = append(cmdArgs, "--signal", signal)
			}

			if skipHealthChecks, ok := args["skip-health-checks"]; ok {
				value, err := strconv.ParseBool(skipHealthChecks)
				if err != nil {
					return nil, fmt.Errorf("invalid value for skip-health-checks: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--skip-health-checks")
				}
			}

			if timeStr, ok := args["time"]; ok {
				cmdArgs = append(cmdArgs, "--time", timeStr)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-run",
		ToolDescription: "Run a machine",
		ToolArgs: map[string]FlyArg{

			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"autostart": {
				Description: "Automatically start a stopped Machine when a network request is received",
				Required:    false,
				Type:        "boolean",
				Default:     "true",
			},
			"autostop": {
				Description: "Automatically stop a Machine when there are no network requests for it",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"off", "stop", "suspend"},
				Default:     "off",
			},
			"command": {
				Description: "Command to run on the machine",
				Required:    false,
				Type:        "string",
			},
			"entrypoint": {
				Description: "The command to override the Docker ENTRYPOINT",
				Required:    false,
				Type:        "string",
			},
			"env": {
				Description: "Set of environment variables in the form of NAME=VALUE pairs.",
				Required:    false,
				Type:        "array",
			},
			"host-dedication-id": {
				Description: "The dedication id of the reserved hosts for your organization (if any)",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "Machine ID, if previously known",
				Required:    false,
				Type:        "string",
			},
			"image": {
				Description: "The image to use for the new machine",
				Required:    true,
				Type:        "string",
			},
			"metadata": {
				Description: "Set of metadata in the form of NAME=VALUE pairs.",
				Required:    false,
				Type:        "array",
			},
			"name": {
				Description: "Name of the new machine. Will be generated if omitted.",
				Required:    false,
				Type:        "string",
			},
			"port": {
				Description: "The external ports and handlers for services, in the format: port[:machinePort][/protocol[:handler[:handler...]]])",
				Required:    false,
				Type:        "array",
			},
			"region": {
				Description: "Region to create the new machine in",
				Required:    false,
				Type:        "string",
			},
			"restart": {
				Description: "Restart policy for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"no", "always", "on-failure"},
			},
			"rm": {
				Description: "Automatically remove the Machine when it exits",
				Required:    false,
				Type:        "boolean",
			},
			"schedule": {
				Description: "Schedule for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"hourly", "daily", "weekly", "monthly"},
			},
			"skip-dns-registration": {
				Description: "Skip DNS registration for the new machine",
				Required:    false,
				Type:        "boolean",
			},
			"standby-for": {
				Description: "For Machines without services, a comma separated list of Machine IDs to act as standby for.",
				Required:    false,
				Type:        "array",
			},
			"use-zstd": {
				Description: "Use zstd compression for the image",
				Required:    false,
				Type:        "boolean",
			},
			"user": {
				Description: "User to run the command as",
				Required:    false,
				Type:        "string",
			},
			"vm-cpu-kind": {
				Description: "The CPU kind to use for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"shared", "dedicated"},
			},
			"vm-cpus": {
				Description: "The number of CPUs to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-gpu-kind": {
				Description: "If set, the GPU model to attach",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"a100-pcie-40gb", "a100-sxm4-80gb", "l40s", "a10", "none"},
			},
			"vm-gpus": {
				Description: "The number of GPUs to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-memory": {
				Description: "The amount of memory (in megabytes) to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-size": {
				Description: `The VM size to set machines to. See "fly platform vm-sizes" for valid values`,
				Required:    false,
				Type:        "string",
			},
			"volume": {
				Description: "Volume to mount, in the form of <volume_id_or_name>:/path/inside/machine[:<options>]",
				Required:    false,
				Type:        "array",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "run"}

			if image, ok := args["image"]; ok {
				cmdArgs = append(cmdArgs, image)
			} else {
				return nil, fmt.Errorf("missing required argument: image")
			}

			if command, ok := args["command"]; ok {
				cmdArgs = append(cmdArgs, command)
			} else {
				return nil, fmt.Errorf("missing required argument: command")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			if autostart, ok := args["autostart"]; ok {
				value, err := strconv.ParseBool(autostart)
				if err != nil {
					return nil, fmt.Errorf("invalid value for autostart: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--autostart")
				}
			}

			if autostop, ok := args["autostop"]; ok {
				cmdArgs = append(cmdArgs, "--autostop", autostop)
			}

			if entrypoint, ok := args["entrypoint"]; ok {
				cmdArgs = append(cmdArgs, "--entrypoint", entrypoint)
			}

			if env, ok := args["env"]; ok {
				cmdArgs = append(cmdArgs, "--env", env)
			}

			if hostDedicationID, ok := args["host-dedication-id"]; ok {
				cmdArgs = append(cmdArgs, "--host-dedication-id", hostDedicationID)
			}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, "--id", id)
			}

			if metadata, ok := args["metadata"]; ok {
				cmdArgs = append(cmdArgs, "--metadata", metadata)
			}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, "--name", name)
			}

			if port, ok := args["port"]; ok {
				cmdArgs = append(cmdArgs, "--port", port)
			}

			if region, ok := args["region"]; ok {
				cmdArgs = append(cmdArgs, "--region", region)
			}

			if restart, ok := args["restart"]; ok {
				cmdArgs = append(cmdArgs, "--restart", restart)
			}

			if rm, ok := args["rm"]; ok {
				value, err := strconv.ParseBool(rm)
				if err != nil {
					return nil, fmt.Errorf("invalid value for rm: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--rm")
				}
			}

			if schedule, ok := args["schedule"]; ok {
				cmdArgs = append(cmdArgs, "--schedule", schedule)
			}

			if skipDnsRegistration, ok := args["skip-dns-registration"]; ok {
				value, err := strconv.ParseBool(skipDnsRegistration)
				if err != nil {
					return nil, fmt.Errorf("invalid value for skip-dns-registration: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--skip-dns-registration")
				}
			}

			if standbyFor, ok := args["standby-for"]; ok {
				cmdArgs = append(cmdArgs, "--standby-for", standbyFor)
			}

			if useZstd, ok := args["use-zstd"]; ok {
				value, err := strconv.ParseBool(useZstd)
				if err != nil {
					return nil, fmt.Errorf("invalid value for use-zstd: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--use-zstd")
				}
			}

			if user, ok := args["user"]; ok {
				cmdArgs = append(cmdArgs, "--user", user)
			}

			if vmCpuKind, ok := args["vm-cpu-kind"]; ok {
				cmdArgs = append(cmdArgs, "--vm-cpu-kind", vmCpuKind)
			}

			if vmCpus, ok := args["vm-cpus"]; ok {
				cmdArgs = append(cmdArgs, "--vm-cpus", vmCpus)
			}

			if vmGpuKind, ok := args["vm-gpu-kind"]; ok {
				cmdArgs = append(cmdArgs, "--vm-gpu-kind", vmGpuKind)
			}

			if vmGpus, ok := args["vm-gpus"]; ok {
				cmdArgs = append(cmdArgs, "--vm-gpus", vmGpus)
			}

			if vmMemory, ok := args["vm-memory"]; ok {
				cmdArgs = append(cmdArgs, "--vm-memory", vmMemory)
			}

			if vmSize, ok := args["vm-size"]; ok {
				cmdArgs = append(cmdArgs, "--vm-size", vmSize)
			}

			if volume, ok := args["volume"]; ok {
				cmdArgs = append(cmdArgs, "--volume", volume)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-start",
		ToolDescription: "Start a Fly machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to start",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "start"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-status",
		ToolDescription: "Show current status of a running machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to show status for",
				Required:    true,
				Type:        "string",
			},
			"display-config": {
				Description: "Display the machine config",
				Required:    false,
				Type:        "boolean",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "status"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			if displayConfig, ok := args["display-config"]; ok {
				value, err := strconv.ParseBool(displayConfig)
				if err != nil {
					return nil, fmt.Errorf("invalid value for display-config: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--display-config")
				}
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-stop",
		ToolDescription: "Stop a Fly machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to stop",
				Required:    true,
				Type:        "string",
			},
			"signal": {
				Description: "Signal to send to the machine",
				Required:    false,
				Type:        "string",
			},
			"timeout": {
				Description: "Seconds to wait before killing the machine",
				Required:    false,
				Type:        "number",
			},
			"wait-timeout": {
				Description: "Seconds to wait for the machine to stop",
				Required:    false,
				Type:        "number",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "stop"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			if signal, ok := args["signal"]; ok {
				cmdArgs = append(cmdArgs, "--signal", signal)
			}

			if timeoutStr, ok := args["timeout"]; ok {
				cmdArgs = append(cmdArgs, "--timeout", timeoutStr)
			}

			if waitTimeoutStr, ok := args["wait-timeout"]; ok {
				cmdArgs = append(cmdArgs, "--wait-timeout", waitTimeoutStr)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-suspend",
		ToolDescription: "Suspend a Fly machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to suspend",
				Required:    true,
				Type:        "string",
			},
			"wait-timeout": {
				Description: "Seconds to wait for the machine to suspend",
				Required:    false,
				Type:        "number",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "suspend"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			if waitTimeoutStr, ok := args["wait-timeout"]; ok {
				cmdArgs = append(cmdArgs, "--wait-timeout", waitTimeoutStr)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-upcordon",
		ToolDescription: "Reactivate all services on a machine",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    false,
				Type:        "string",
			},
			"id": {
				Description: "ID of the machine to upcordon",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "upcordon"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-machine-update",
		ToolDescription: "Update a machine",
		ToolArgs: map[string]FlyArg{

			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"id": {
				Description: "Machine ID",
				Required:    true,
				Type:        "string",
			},
			"autostart": {
				Description: "Automatically start a stopped Machine when a network request is received",
				Required:    false,
				Type:        "boolean",
				Default:     "true",
			},
			"autostop": {
				Description: "Automatically stop a Machine when there are no network requests for it",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"off", "stop", "suspend"},
				Default:     "off",
			},
			"command": {
				Description: "Command to run on the machine",
				Required:    false,
				Type:        "string",
			},
			"entrypoint": {
				Description: "The command to override the Docker ENTRYPOINT",
				Required:    false,
				Type:        "string",
			},
			"env": {
				Description: "Set of environment variables in the form of NAME=VALUE pairs.",
				Required:    false,
				Type:        "array",
			},
			"host-dedication-id": {
				Description: "The dedication id of the reserved hosts for your organization (if any)",
				Required:    false,
				Type:        "string",
			},
			"image": {
				Description: "The image to use for the new machine",
				Required:    false,
				Type:        "string",
			},
			"metadata": {
				Description: "Set of metadata in the form of NAME=VALUE pairs.",
				Required:    false,
				Type:        "array",
			},
			"port": {
				Description: "The external ports and handlers for services, in the format: port[:machinePort][/protocol[:handler[:handler...]]])",
				Required:    false,
				Type:        "array",
			},
			"restart": {
				Description: "Restart policy for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"no", "always", "on-failure"},
			},
			"schedule": {
				Description: "Schedule for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"hourly", "daily", "weekly", "monthly"},
			},
			"skip-dns-registration": {
				Description: "Skip DNS registration for the new machine",
				Required:    false,
				Type:        "boolean",
			},
			"standby-for": {
				Description: "For Machines without services, a comma separated list of Machine IDs to act as standby for.",
				Required:    false,
				Type:        "array",
			},
			"use-zstd": {
				Description: "Use zstd compression for the image",
				Required:    false,
				Type:        "boolean",
			},
			"vm-cpu-kind": {
				Description: "The CPU kind to use for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"shared", "dedicated"},
			},
			"vm-cpus": {
				Description: "The number of CPUs to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-gpu-kind": {
				Description: "If set, the GPU model to attach",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"a100-pcie-40gb", "a100-sxm4-80gb", "l40s", "a10", "none"},
			},
			"vm-gpus": {
				Description: "The number of GPUs to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-memory": {
				Description: "The amount of memory (in megabytes) to use for the new machine",
				Required:    false,
				Type:        "number",
			},
			"vm-size": {
				Description: `The VM size to set machines to. See "fly platform vm-sizes" for valid values`,
				Required:    false,
				Type:        "string",
			},
			"wait-timeout": {
				Description: "Seconds to wait for the machine to update",
				Required:    false,
				Type:        "number",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"machine", "create"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("missing required argument: id")
			}

			if image, ok := args["image"]; ok {
				cmdArgs = append(cmdArgs, "--image", image)
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			if autostart, ok := args["autostart"]; ok {
				value, err := strconv.ParseBool(autostart)
				if err != nil {
					return nil, fmt.Errorf("invalid value for autostart: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--autostart")
				}
			}

			if autostop, ok := args["autostop"]; ok {
				cmdArgs = append(cmdArgs, "--autostop", autostop)
			}

			if entrypoint, ok := args["entrypoint"]; ok {
				cmdArgs = append(cmdArgs, "--entrypoint", entrypoint)
			}

			if env, ok := args["env"]; ok {
				cmdArgs = append(cmdArgs, "--env", env)
			}

			if hostDedicationID, ok := args["host-dedication-id"]; ok {
				cmdArgs = append(cmdArgs, "--host-dedication-id", hostDedicationID)
			}

			if metadata, ok := args["metadata"]; ok {
				cmdArgs = append(cmdArgs, "--metadata", metadata)
			}

			if port, ok := args["port"]; ok {
				cmdArgs = append(cmdArgs, "--port", port)
			}

			if restart, ok := args["restart"]; ok {
				cmdArgs = append(cmdArgs, "--restart", restart)
			}

			if rm, ok := args["rm"]; ok {
				value, err := strconv.ParseBool(rm)
				if err != nil {
					return nil, fmt.Errorf("invalid value for rm: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--rm")
				}
			}

			if schedule, ok := args["schedule"]; ok {
				cmdArgs = append(cmdArgs, "--schedule", schedule)
			}

			if skipDnsRegistration, ok := args["skip-dns-registration"]; ok {
				value, err := strconv.ParseBool(skipDnsRegistration)
				if err != nil {
					return nil, fmt.Errorf("invalid value for skip-dns-registration: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--skip-dns-registration")
				}
			}

			if standbyFor, ok := args["standby-for"]; ok {
				cmdArgs = append(cmdArgs, "--standby-for", standbyFor)
			}

			if useZstd, ok := args["use-zstd"]; ok {
				value, err := strconv.ParseBool(useZstd)
				if err != nil {
					return nil, fmt.Errorf("invalid value for use-zstd: %v", err)
				} else if value {
					cmdArgs = append(cmdArgs, "--use-zstd")
				}
			}

			if vmCpuKind, ok := args["vm-cpu-kind"]; ok {
				cmdArgs = append(cmdArgs, "--vm-cpu-kind", vmCpuKind)
			}

			if vmCpus, ok := args["vm-cpus"]; ok {
				cmdArgs = append(cmdArgs, "--vm-cpus", vmCpus)
			}

			if vmGpuKind, ok := args["vm-gpu-kind"]; ok {
				cmdArgs = append(cmdArgs, "--vm-gpu-kind", vmGpuKind)
			}

			if vmGpus, ok := args["vm-gpus"]; ok {
				cmdArgs = append(cmdArgs, "--vm-gpus", vmGpus)
			}

			if vmMemory, ok := args["vm-memory"]; ok {
				cmdArgs = append(cmdArgs, "--vm-memory", vmMemory)
			}

			if vmSize, ok := args["vm-size"]; ok {
				cmdArgs = append(cmdArgs, "--vm-size", vmSize)
			}

			if waitTimeout, ok := args["wait-timeout"]; ok {
				cmdArgs = append(cmdArgs, "--wait-timeout", waitTimeout)
			}

			return cmdArgs, nil
		},
	},
}
View Source
var OrgCommands = []FlyCommand{
	{
		ToolName:        "fly-orgs-create",
		ToolDescription: "Create a new organization. Other users can be invited to join the organization later.",
		ToolArgs: map[string]FlyArg{
			"name": {
				Description: "Name of the organization",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"orgs", "create"}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, name)
			} else {
				return nil, fmt.Errorf("missing required argument: name")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-orgs-delete",
		ToolDescription: "Delete an organization. All apps and machines in the organization will be deleted.",
		ToolArgs: map[string]FlyArg{
			"slug": {
				Description: "Slug of the organization to delete",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"orgs", "delete"}

			if slug, ok := args["slug"]; ok {
				cmdArgs = append(cmdArgs, slug)
			} else {
				return nil, fmt.Errorf("missing required argument: slug")
			}

			cmdArgs = append(cmdArgs, "--yes")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-orgs-invite",
		ToolDescription: "Invite a user, by email, to join organization. The invitation will be sent, and the user will be pending until they respond.",
		ToolArgs: map[string]FlyArg{
			"slug": {
				Description: "Slug of the organization to invite the user to",
				Required:    true,
				Type:        "string",
			},
			"email": {
				Description: "Email address of the user to invite",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"orgs", "invite"}

			if slug, ok := args["slug"]; ok {
				cmdArgs = append(cmdArgs, slug)
			} else {
				return nil, fmt.Errorf("missing required argument: slug")
			}

			if email, ok := args["email"]; ok {
				cmdArgs = append(cmdArgs, email)
			} else {
				return nil, fmt.Errorf("missing required argument: email")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-orgs-list",
		ToolDescription: "List all organizations the user is a member of.  Keys are names of the organizations, values are slugs.",
		ToolArgs:        map[string]FlyArg{},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"orgs", "list", "--json"}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-orgs-remove",
		ToolDescription: "Remove a user from an organization. The user will no longer have access to the organization.",
		ToolArgs: map[string]FlyArg{
			"slug": {
				Description: "Slug of the organization to remove the user from",
				Required:    true,
				Type:        "string",
			},
			"email": {
				Description: "Email address of the user to remove",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"orgs", "remove"}

			if slug, ok := args["slug"]; ok {
				cmdArgs = append(cmdArgs, slug)
			} else {
				return nil, fmt.Errorf("missing required argument: slug")
			}

			if email, ok := args["email"]; ok {
				cmdArgs = append(cmdArgs, email)
			} else {
				return nil, fmt.Errorf("missing required argument: email")
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-orgs-show",
		ToolDescription: "Shows information about an organization. Includes name, slug and type. Summarizes user permissions, DNS zones and associated member. Details full list of members and roles.",
		ToolArgs: map[string]FlyArg{
			"slug": {
				Description: "Slug of the organization to show",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"orgs", "show"}

			if slug, ok := args["slug"]; ok {
				cmdArgs = append(cmdArgs, slug)
			} else {
				return nil, fmt.Errorf("missing required argument: slug")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},
}
View Source
var PlatformCommands = []FlyCommand{
	{
		ToolName:        "fly-platform-regions",
		ToolDescription: platform.RegionsCommandDesc,
		ToolArgs:        map[string]FlyArg{},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"platform", "regions", "--json"}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-platform-status",
		ToolDescription: "Get the status of Fly's platform",
		ToolArgs:        map[string]FlyArg{},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"platform", "status", "--json"}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-platform-vm-sizes",
		ToolDescription: "Get a list of VM sizes available for Fly apps",
		ToolArgs:        map[string]FlyArg{},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"platform", "vm-sizes", "--json"}

			return cmdArgs, nil
		},
	},
}
View Source
var SecretsCommands = []FlyCommand{
	{
		ToolName:        "fly-secrets-deploy",
		ToolDescription: "Deploy secrets to the specified app",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"secrets", "deploy"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			return cmdArgs, nil
		},
	},
	{
		ToolName:        "fly-secrets-list",
		ToolDescription: "List secrets for the specified app",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"secrets", "list", "--json"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("missing required argument: app")
			}

			return cmdArgs, nil
		},
	},
	{
		ToolName:        "fly-secrets-set",
		ToolDescription: "Set secrets for the specified app; secrets are staged for the next deploy",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"keyvalues": {
				Description: "Secrets to set in KEY=VALUE format",
				Required:    true,
				Type:        "hash",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"secrets", "set", "--stage"}

			app, ok := args["app"]
			if !ok || app == "" {
				return nil, fmt.Errorf("missing required argument: app")
			}
			cmdArgs = append(cmdArgs, "-a", app)

			keyvalues, ok := args["keyvalues"]
			if ok && keyvalues != "" {
				args, err := shlex.Split(keyvalues)
				if err != nil {
					return nil, fmt.Errorf("failed to parse keyvalues: %w", err)
				}
				cmdArgs = append(cmdArgs, args...)
			}

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-secrets-unset",
		ToolDescription: "Unset secrets for the specified app; changes are staged for the next deploy",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"names": {
				Description: "Names of secrets to unset",
				Required:    true,
				Type:        "array",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"secrets", "unset", "--stage"}

			app, ok := args["app"]
			if !ok || app == "" {
				return nil, fmt.Errorf("missing required argument: app")
			}
			cmdArgs = append(cmdArgs, "-a", app)

			names, ok := args["names"]
			if ok && names != "" {
				cmdArgs = append(cmdArgs, strings.Split(names, ",")...)
			}

			return cmdArgs, nil
		},
	},
}
View Source
var StatusCommands = []FlyCommand{
	{
		ToolName:        "fly-status",
		ToolDescription: "Get status of a Fly.io app",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
		},
		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"status", "--json"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			}

			return cmdArgs, nil
		},
	},
}
View Source
var VolumeCommands = []FlyCommand{
	{
		ToolName:        "fly-volumes-create",
		ToolDescription: "Create a new volume for an app. Volumes are persistent storage for Fly Machines.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"name": {
				Description: "name of the volume",
				Required:    true,
				Type:        "string",
			},
			"encrypt": {
				Description: "Encrypt the volume",
				Required:    false,
				Type:        "boolean",
				Default:     "true",
			},
			"region": {
				Description: "Region to create the volume in",
				Required:    true,
				Type:        "string",
			},
			"size": {
				Description: "Size of the volume in GB",
				Required:    false,
				Type:        "number",
				Default:     "1",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"volume", "create"}

			if name, ok := args["name"]; ok {
				cmdArgs = append(cmdArgs, name)
			} else {
				return nil, fmt.Errorf("name argument is required")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("app argument is required")
			}

			if encrypt, ok := args["encrypt"]; ok {
				encryptBool, err := strconv.ParseBool(encrypt)
				if err != nil {
					return nil, fmt.Errorf("invalid value for encrypt: %v", err)
				} else if !encryptBool {
					cmdArgs = append(cmdArgs, "--no-encryption")
				}
			}

			if region, ok := args["region"]; ok {
				cmdArgs = append(cmdArgs, "--region", region)
			} else {
				return nil, fmt.Errorf("region argument is required")
			}

			if size, ok := args["size"]; ok {
				cmdArgs = append(cmdArgs, "--size", size)
			}

			cmdArgs = append(cmdArgs, "--yes", "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-volumes-destroy",
		ToolDescription: "Destroy one or more volumes. When you destroy a volume, you permanently delete all its data.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"id": {
				Description: "id of the volume",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"volume", "destroy"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("id argument is required")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("app argument is required")
			}

			cmdArgs = append(cmdArgs, "--yes", "--verbose")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-volumes-extend",
		ToolDescription: "Extend a volume to a larger size. You can only extend a volume to a larger size.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"id": {
				Description: "id of the volume",
				Required:    true,
				Type:        "string",
			},
			"size": {
				Description: "Size of the volume in Gigabytes",
				Required:    true,
				Type:        "number",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"volume", "extend"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("id argument is required")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("app argument is required")
			}

			if size, ok := args["size"]; ok {
				cmdArgs = append(cmdArgs, "--size", size)
			} else {
				return nil, fmt.Errorf("size argument is required")
			}

			cmdArgs = append(cmdArgs, "--yes", "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-volumes-fork",
		ToolDescription: "Fork the specified volume. Volume forking creates an independent copy of a storage volume for backup, testing, and experimentation without altering the original data.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"id": {
				Description: "id of the volume",
				Required:    true,
				Type:        "string",
			},
			"region": {
				Description: "Region to create the new volume in",
				Required:    false,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"volume", "fork"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("id argument is required")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("app argument is required")
			}

			if region, ok := args["region"]; ok {
				cmdArgs = append(cmdArgs, "--region", region)
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-volumes-list",
		ToolDescription: "List all volumes for an app. Volumes are persistent storage for Fly Machines.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"all": {
				Description: "Show all volumes, including those that in destroyed states",
				Required:    false,
				Type:        "boolean",
				Default:     "false",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"volume", "list"}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("app argument is required")
			}

			if all, ok := args["all"]; ok {
				allBool, err := strconv.ParseBool(all)
				if err != nil {
					return nil, fmt.Errorf("invalid value for all: %v", err)
				} else if allBool {
					cmdArgs = append(cmdArgs, "--all")
				}
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-volumes-show",
		ToolDescription: "Show details about a volume. Volumes are persistent storage for Fly Machines.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"id": {
				Description: "id of the volume",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"volume", "show"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("id argument is required")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("app argument is required")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-volumes-snapshots-create",
		ToolDescription: "Create a snapshot of a volume. Snapshots are point-in-time copies of a volume.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"id": {
				Description: "id of the volume",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"volume", "snapshots", "create"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("id argument is required")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("app argument is required")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-volumes-snapshots-list",
		ToolDescription: "List all snapshots for a volume. Snapshots are point-in-time copies of a volume.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"id": {
				Description: "id of the volume",
				Required:    true,
				Type:        "string",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"volume", "snapshots", "list"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("id argument is required")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("app argument is required")
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},

	{
		ToolName:        "fly-volumes-update",
		ToolDescription: "Update a volume. You can activate or deactivate snapshotting, and change the snapshot's retention period.",
		ToolArgs: map[string]FlyArg{
			"app": {
				Description: "Name of the app",
				Required:    true,
				Type:        "string",
			},
			"id": {
				Description: "id of the volume",
				Required:    true,
				Type:        "string",
			},
			"scheduled-snapshots": {
				Description: "Enable or disable scheduled snapshots",
				Required:    false,
				Type:        "boolean",
			},
			"snapshot-retention": {
				Description: "Retention period for snapshots in days",
				Required:    false,
				Type:        "number",
			},
		},

		Builder: func(args map[string]string) ([]string, error) {
			cmdArgs := []string{"volume", "update"}

			if id, ok := args["id"]; ok {
				cmdArgs = append(cmdArgs, id)
			} else {
				return nil, fmt.Errorf("id argument is required")
			}

			if app, ok := args["app"]; ok {
				cmdArgs = append(cmdArgs, "-a", app)
			} else {
				return nil, fmt.Errorf("app argument is required")
			}

			if scheduledSnapshots, ok := args["scheduled-snapshots"]; ok {
				scheduledSnapshotsBool, err := strconv.ParseBool(scheduledSnapshots)
				if err != nil {
					return nil, fmt.Errorf("invalid value for scheduled-snapshots: %v", err)
				} else if scheduledSnapshotsBool {
					cmdArgs = append(cmdArgs, "--scheduled-snapshots=true")
				} else {
					cmdArgs = append(cmdArgs, "--scheduled-snapshots=false")
				}
			}

			if snapshotRetention, ok := args["snapshot-retention"]; ok {
				cmdArgs = append(cmdArgs, "--snapshot-retention", snapshotRetention)
			}

			cmdArgs = append(cmdArgs, "--json")

			return cmdArgs, nil
		},
	},
}

Functions

This section is empty.

Types

type FlyArg

type FlyArg struct {
	Description string
	Required    bool
	Type        string // "string", "enum", "array", "number", "boolean"
	Default     string
	Enum        []string
}

FlyArg represents an argument for a Fly command

type FlyCommand

type FlyCommand struct {
	ToolName        string
	ToolDescription string
	ToolArgs        map[string]FlyArg
	Builder         func(args map[string]string) ([]string, error)
}

FlyCommand represents a command for the Fly MCP server

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL