mcpServer

package
v0.3.155 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2025 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.Split(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-fail"},
			},
			"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", "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-fail"},
			},
			"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", "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-fail"},
			},
			"schedule": {
				Description: "Schedule for the new machine",
				Required:    false,
				Type:        "enum",
				Enum:        []string{"hourly", "daily", "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