Skip to main content
Glama

microsandbox

by microsandbox
msb.rs18.7 kB
use std::{error::Error, path::PathBuf}; use crate::styles; use clap::Parser; use microsandbox_core::oci::Reference; use typed_path::Utf8UnixPathBuf; //------------------------------------------------------------------------------------------------- // Types //------------------------------------------------------------------------------------------------- /// msb (microsandbox) is a tool for managing lightweight sandboxes and images #[derive(Debug, Parser)] #[command(name = "msb", author, styles=styles::styles())] pub struct MicrosandboxArgs { /// The subcommand to run #[command(subcommand)] pub subcommand: Option<MicrosandboxSubcommand>, /// Show version #[arg(short = 'V', long, global = true)] pub version: bool, /// Show logs with error level #[arg(long, global = true)] pub error: bool, /// Show logs with warn level #[arg(long, global = true)] pub warn: bool, /// Show logs with info level #[arg(long, global = true)] pub info: bool, /// Show logs with debug level #[arg(long, global = true)] pub debug: bool, /// Show logs with trace level #[arg(long, global = true)] pub trace: bool, } /// Available subcommands for managing services #[derive(Debug, Parser)] pub enum MicrosandboxSubcommand { /// Initialize a new microsandbox project #[command(name = "init")] Init { /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, }, /// Add a new sandbox to the project #[command(name = "add")] Add { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Names of components to add #[arg(required = true)] names: Vec<String>, /// Image to use #[arg(short, long)] image: String, /// Memory in MiB #[arg(long)] memory: Option<u32>, /// Number of CPUs #[arg(long, alias = "cpu")] cpus: Option<u32>, /// Volume mappings, format: <host_path>:<container_path> #[arg(short, long = "volume", name = "VOLUME")] volumes: Vec<String>, /// Port mappings, format: <host_port>:<container_port> #[arg(short, long = "port", name = "PORT")] ports: Vec<String>, /// Environment variables, format: <key>=<value> #[arg(long = "env", name = "ENV")] envs: Vec<String>, /// Environment file #[arg(long)] env_file: Option<Utf8UnixPathBuf>, /// Dependencies #[arg(long)] depends_on: Vec<String>, /// Working directory #[arg(long)] workdir: Option<Utf8UnixPathBuf>, /// Shell to use #[arg(long)] shell: Option<String>, /// Scripts to add #[arg(long = "script", name = "SCRIPT", value_parser = parse_key_val::<String, String>)] scripts: Vec<(String, String)>, /// Start script #[arg(long)] start: Option<String>, /// Files to import, format: <name>=<path> #[arg(long = "import", name = "IMPORT", value_parser = parse_key_val::<String, String>)] imports: Vec<(String, String)>, /// Files to export, format: <name>=<path> #[arg(long = "export", name = "EXPORT", value_parser = parse_key_val::<String, String>)] exports: Vec<(String, String)>, /// Network scope, options: local, public, any, none #[arg(long)] scope: Option<String>, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, }, /// Remove a sandbox from the project #[command(name = "remove", alias = "rm")] Remove { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Names of components to remove #[arg(required = true)] names: Vec<String>, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, }, /// List sandboxes defined in the project #[command(name = "list")] List { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, }, /// Show logs of a build or sandbox #[command(name = "log")] Log { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Name of the component #[arg(required = true)] name: String, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, /// Follow the logs #[arg(short = 'F', long)] follow: bool, /// Number of lines to show from the end #[arg(short, long)] tail: Option<usize>, }, /// Show tree of layers that make up a sandbox #[command(name = "tree")] Tree { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Names of components to show #[arg(required = true)] names: Vec<String>, /// Maximum depth level #[arg(short = 'L', long)] level: Option<usize>, }, /// Run a sandbox defined in the project #[command(name = "run", alias = "r")] Run { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Name of the component #[arg(required = true, name = "NAME[~SCRIPT]")] name: String, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, /// Run sandbox in the background #[arg(short, long)] detach: bool, /// Execute a command within the sandbox #[arg(short, long, short_alias = 'x')] exec: Option<String>, /// Additional arguments after `--`. Passed to the script or exec. #[arg(last = true)] args: Vec<String>, }, /// Open a shell in a sandbox #[command(name = "shell")] Shell { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Name of the component #[arg(required = true)] name: String, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, /// Run sandbox in the background #[arg(short, long)] detach: bool, /// Additional arguments after `--`. Passed to the shell. #[arg(last = true)] args: Vec<String>, }, /// Run a temporary sandbox #[command(name = "exe", alias = "x")] Exe { /// Whether command should apply to a sandbox #[arg(short, long)] image: bool, /// Name of the image #[arg(required = true, name = "NAME[~SCRIPT]")] name: String, /// Number of CPUs #[arg(long, alias = "cpu")] cpus: Option<u8>, /// Memory in MB #[arg(long)] memory: Option<u32>, /// Volume mappings, format: <host_path>:<container_path> #[arg(short, long = "volume", name = "VOLUME")] volumes: Vec<String>, /// Port mappings, format: <host_port>:<container_port> #[arg(short, long = "port", name = "PORT")] ports: Vec<String>, /// Environment variables, format: <key>=<value> #[arg(long = "env", name = "ENV")] envs: Vec<String>, /// Working directory #[arg(long)] workdir: Option<Utf8UnixPathBuf>, /// Network scope, options: local, public, any, none #[arg(long)] scope: Option<String>, /// Execute a command within the sandbox #[arg(short, long, short_alias = 'x')] exec: Option<String>, /// Additional arguments after `--`. Passed to the script or exec. #[arg(last = true)] args: Vec<String>, }, /// Install a script from an image #[command(name = "install", alias = "i")] Install { /// Whether command should apply to a sandbox #[arg(short, long)] image: bool, /// Name of the image #[arg(required = true, name = "NAME[~SCRIPT]")] name: String, /// Alias for the script #[arg()] alias: Option<String>, /// Number of CPUs #[arg(long, alias = "cpu")] cpus: Option<u8>, /// Memory in MB #[arg(long)] memory: Option<u32>, /// Volume mappings, format: <host_path>:<container_path> #[arg(short, long = "volume", name = "VOLUME")] volumes: Vec<String>, /// Port mappings, format: <host_port>:<container_port> #[arg(short, long = "port", name = "PORT")] ports: Vec<String>, /// Environment variables, format: <key>=<value> #[arg(long = "env", name = "ENV")] envs: Vec<String>, /// Working directory #[arg(long)] workdir: Option<Utf8UnixPathBuf>, /// Network scope, options: local, public, any, none #[arg(long)] scope: Option<String>, /// Execute a command within the sandbox #[arg(short, long, short_alias = 'x')] exec: Option<String>, /// Additional arguments after `--`. Passed to the script or exec. #[arg(last = true)] args: Vec<String>, }, /// Uninstall a script #[command(name = "uninstall")] Uninstall { /// Script to uninstall script: Option<String>, }, /// Start or stop project sandboxes based on configuration #[command(name = "apply")] Apply { /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, /// Run sandboxes in the background #[arg(short, long)] detach: bool, }, /// Run a project's sandboxes #[command(name = "up")] Up { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Names of components to start. If omitted, starts all sandboxes defined in the configuration. names: Vec<String>, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, /// Run sandboxes in the background #[arg(short, long)] detach: bool, }, /// Stop a project's sandboxes #[command(name = "down")] Down { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Names of components to stop. If omitted, stops all sandboxes defined in the configuration. names: Vec<String>, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, }, /// Show statuses of a project's running sandboxes #[command(name = "status", alias = "ps", alias = "stat")] Status { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Whether command should apply to a build sandbox #[arg(short, long)] build: bool, /// Names of components to show status for #[arg()] names: Vec<String>, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, }, /// Clean cached sandbox layers, metadata, etc. #[command(name = "clean")] Clean { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Name of the component #[arg()] name: Option<String>, /// Clean user-level caches. This cleans $MICROSANDBOX_HOME #[arg(short, long)] user: bool, /// Clean all #[arg(short, long)] all: bool, /// Path to the sandbox file or the project directory #[arg(short, long)] file: Option<PathBuf>, /// Force clean #[arg(short = 'F', long)] force: bool, }, /// Build images #[command(name = "build")] Build { /// Build from sandbox #[arg(short, long)] sandbox: bool, /// Build from build definition #[arg(short, long)] build: bool, /// Names of components to build #[arg(required = true)] names: Vec<String>, /// Create a snapshot #[arg(long)] snapshot: bool, }, /// Pull image from a registry #[command(name = "pull")] Pull { /// Whether command should apply to an image #[arg(short, long)] image: bool, /// Name of the image #[arg(required = true)] name: Reference, /// Path to store the layer files #[arg(short = 'L', long)] layer_path: Option<PathBuf>, }, /// Login to a registry #[command(name = "login")] Login, /// Push image to a registry #[command(name = "push")] Push { /// Whether command should apply to an image #[arg(short, long)] image: bool, /// Name of the image #[arg(required = true)] name: String, }, /// Manage microsandbox itself #[command(name = "self")] Self_ { /// Action to perform #[arg(value_enum)] action: SelfAction, }, /// Start a sandbox server for orchestrating and working with sandboxes #[command(name = "server")] Server { /// The subcommand to run #[command(subcommand)] subcommand: ServerSubcommand, }, /// Print version of microsandbox #[command(name = "version")] Version, } /// Subcommands for the server subcommand #[derive(Debug, Parser)] pub enum ServerSubcommand { /// Start the sandbox server which is also an MCP server Start { /// Host to listen on #[arg(long)] host: Option<String>, /// Port to listen on #[arg(long)] port: Option<u16>, /// Path to the namespace directory #[arg(short = 'p', long = "path")] namespace_dir: Option<PathBuf>, /// Run server in development mode #[arg(long = "dev")] dev_mode: bool, /// Set secret key for server. Automatically generated if not provided. #[arg(short, long)] key: Option<String>, /// Run server in the background #[arg(short, long)] detach: bool, /// Reset the server key #[arg(short, long)] reset_key: bool, }, /// Stop the sandbox server Stop, /// Generate a new API key #[command(name = "keygen")] Keygen { /// Token expiration duration. format: 1s, 2m, 3h, 4d, 5w, 6mo, 7y #[arg(long)] expire: Option<String>, /// Namespace for the API key. If not specified, generates a key for all namespaces. #[arg(short, long)] namespace: Option<String>, }, /// Show logs of a sandbox #[command(name = "log")] Log { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Name of the component #[arg(required = true)] name: String, /// Namespace for the logs #[arg(short, long)] namespace: String, /// Follow the logs #[arg(short, long)] follow: bool, /// Number of lines to show from the end #[arg(short, long)] tail: Option<usize>, }, /// List sandboxes in a namespace #[command(name = "list")] List { /// Namespace to list sandboxes from. If not provided, lists sandboxes from all namespaces. #[arg(short, long)] namespace: Option<String>, }, /// Show server status #[command(name = "status")] Status { /// Whether command should apply to a sandbox #[arg(short, long)] sandbox: bool, /// Name of the component #[arg()] names: Vec<String>, /// Namespace to show status for. If not provided, shows status for all namespaces. #[arg(short, long)] namespace: Option<String>, }, /// SSH into a sandbox #[command(name = "ssh")] Ssh { /// Namespace for the SSH key #[arg(short, long, required = true)] namespace: String, /// Whether to SSH into a sandbox #[arg(short, long)] sandbox: bool, /// Name of the sandbox #[arg(required = true)] name: String, }, } /// Actions for the self subcommand #[derive(Debug, Clone, clap::ValueEnum)] pub enum SelfAction { /// Upgrade microsandbox Upgrade, /// Uninstall microsandbox Uninstall, } //------------------------------------------------------------------------------------------------- // Functions: Helpers //------------------------------------------------------------------------------------------------- fn parse_key_val<T, U>(s: &str) -> Result<(T, U), Box<dyn Error + Send + Sync + 'static>> where T: std::str::FromStr, T::Err: Error + Send + Sync + 'static, U: std::str::FromStr, U::Err: Error + Send + Sync + 'static, { let pos = s .find('=') .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?; Ok((s[..pos].parse()?, s[pos + 1..].parse()?)) }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/microsandbox/microsandbox'

If you have feedback or need assistance with the MCP directory API, please join our Discord server