Skip to main content
Glama

microsandbox

by microsandbox
rpc_command.rs8.21 kB
//! Example demonstrating the microsandbox-portal RPC command execution. //! //! This example showcases how to use the JSON-RPC API to execute system commands //! and retrieve their output via the microsandbox-portal service. It demonstrates: //! //! - Connecting to the portal server //! - Sending command execution requests //! - Processing command output and exit codes //! - Handling different command types //! //! # API Methods Demonstrated //! //! - `sandbox.command.run`: Execute a command in a sandboxed environment //! //! # Running the Example //! //! First, start the portal server: //! //! ```bash //! # From the monocore directory: //! cargo run --bin portal //! ``` //! //! Then, in another terminal, run this example: //! //! ```bash //! cargo run --example rpc_command //! ``` //! //! # Requirements //! //! - A running microsandbox-portal server on localhost:4444 //! //! # Example Output //! //! The example will display the RPC results and the output from each command execution: //! //! ```text //! 📁 Running 'ls' command: //! Command: ls //! Args: ["-la"] //! Exit code: 0 //! Success: true //! //! Output: //! [stdout] total 92 //! [stdout] drwxr-xr-x 13 user staff 416 Jul 15 10:30 . //! [stdout] drwxr-xr-x 6 user staff 192 Jul 15 10:20 .. //! [stdout] -rw-r--r-- 1 user staff 2476 Jul 15 10:30 Cargo.toml //! [stdout] drwxr-xr-x 4 user staff 128 Jul 15 10:20 examples //! [stdout] drwxr-xr-x 6 user staff 192 Jul 15 10:30 lib //! [stdout] drwxr-xr-x 4 user staff 128 Jul 15 10:20 src //! [stdout] drwxr-xr-x 12 user staff 384 Jul 15 10:20 target //! ``` //! //! # Note //! //! This example demonstrates how to interact with the microsandbox-portal via //! JSON-RPC for command execution. In a real application, you might want to implement //! additional error handling and more sophisticated request/response processing. use anyhow::Result; use reqwest::Client; use serde_json::{json, Value}; // Import the parameter types from the microsandbox-portal crate use microsandbox_portal::payload::{JsonRpcRequest, SandboxCommandRunParams, JSONRPC_VERSION}; //-------------------------------------------------------------------------------------------------- // Functions //-------------------------------------------------------------------------------------------------- /// Send a JSON-RPC request to the portal server async fn send_rpc_request<T: serde::Serialize>( client: &Client, method: &str, params: T, ) -> Result<Value> { // Create a properly structured JSON-RPC request let request = JsonRpcRequest { jsonrpc: JSONRPC_VERSION.to_string(), method: method.to_string(), params: serde_json::to_value(params)?, id: Some(Value::from(1)), }; let response = client .post("http://127.0.0.1:4444/api/v1/rpc") .json(&request) .send() .await? .json::<Value>() .await?; // Check for errors in the JSON-RPC error field if response.get("error").is_some() { let error = &response["error"]; eprintln!( "RPC Error {}: {}", error["code"].as_i64().unwrap_or(0), error["message"].as_str().unwrap_or("Unknown error") ); anyhow::bail!( "RPC request failed: {}", error["message"].as_str().unwrap_or("Unknown error") ); } // Extract the result or return empty object if it doesn't exist let result = response.get("result").cloned().unwrap_or(json!({})); Ok(result) } /// Print command output lines from JSON fn print_output_lines(output: &Value) { if let Some(output_array) = output.as_array() { if output_array.is_empty() { println!("No output lines found."); } else { for line in output_array { let stream = line .get("stream") .and_then(|v| v.as_str()) .unwrap_or("unknown"); let text = line.get("text").and_then(|v| v.as_str()).unwrap_or(""); println!("[{}] {}", stream, text); } } } else { println!("No output found in response."); } } #[tokio::main] async fn main() -> Result<()> { // Create HTTP client let client = Client::new(); // Execute a simple 'ls' command using the typed params println!("\n📁 Running 'ls' command:"); let ls_params = SandboxCommandRunParams { command: "ls".to_string(), args: vec!["-la".to_string()], timeout: Some(30), // Add a 30 second timeout }; let result = send_rpc_request(&client, "sandbox.command.run", ls_params).await?; // Extract command execution details let command = result .get("command") .and_then(|v| v.as_str()) .unwrap_or("unknown"); let args = result .get("args") .and_then(|v| v.as_array()) .map(|arr| format!("{:?}", arr)) .unwrap_or_else(|| "[]".to_string()); let exit_code = result .get("exit_code") .and_then(|v| v.as_i64()) .unwrap_or(-1); let success = result .get("success") .and_then(|v| v.as_bool()) .unwrap_or(false); println!("Command: {}", command); println!("Args: {}", args); println!("Exit code: {}", exit_code); println!("Success: {}", success); // Print the output lines println!("\nOutput from execute response:"); if let Some(output) = result.get("output") { print_output_lines(output); } else { println!("No output found in response."); } // Execute another command with environment variables using the typed params println!("\n🔄 Running 'echo' command:"); let echo_params = SandboxCommandRunParams { command: "echo".to_string(), args: vec!["Hello from the sandbox!".to_string()], timeout: None, // No timeout needed for simple echo command }; let result = send_rpc_request(&client, "sandbox.command.run", echo_params).await?; // Extract command execution details let command = result .get("command") .and_then(|v| v.as_str()) .unwrap_or("unknown"); let args = result .get("args") .and_then(|v| v.as_array()) .map(|arr| format!("{:?}", arr)) .unwrap_or_else(|| "[]".to_string()); let exit_code = result .get("exit_code") .and_then(|v| v.as_i64()) .unwrap_or(-1); let success = result .get("success") .and_then(|v| v.as_bool()) .unwrap_or(false); println!("Command: {}", command); println!("Args: {}", args); println!("Exit code: {}", exit_code); println!("Success: {}", success); // Print the output lines println!("\nOutput from execute response:"); if let Some(output) = result.get("output") { print_output_lines(output); } else { println!("No output found in response."); } // Execute a command that will fail to demonstrate error handling println!("\n❌ Running a command that will fail:"); let fail_params = SandboxCommandRunParams { command: "nonexistent_command".to_string(), args: vec![], timeout: Some(5), // Short timeout }; // This will likely fail, so handle the error case match send_rpc_request(&client, "sandbox.command.run", fail_params).await { Ok(result) => { // Still might get a result with error details let exit_code = result .get("exit_code") .and_then(|v| v.as_i64()) .unwrap_or(-1); println!("Command executed but failed with exit code: {}", exit_code); // Print any output/error messages println!("\nError output:"); if let Some(output) = result.get("output") { print_output_lines(output); } else { println!("No error output found in response."); } } Err(e) => { println!("Failed to execute nonexistent command: {}", e); } } println!("\nCommand execution examples completed!"); Ok(()) }

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