DEV Community

xbill for Google Developer Experts

Posted on • Originally published at xbill999.Medium on

Building a Rust System Info Tool with Gemini CLI, and Cloud Run

This article leverages the Gemini CLI and the underlying Gemini LLM to develop native compiled code built in the Rust Language for system information. A fully functional tool is developed in Rust and then deployed to Google Cloud Run.

What is Rust?

Rust is a high performance, memory safe, compiled language:

Rust

Rust provides memory safe operations beyond C/C++ and also can provide exceptional performance gains as it is compiled directly to native binaries.

Initial Environment Setup

The environment is meant to be run from a Bash like shell. You can run this from a Linux VM, ChromeOS Linux VM, Firebase Studio environment, or any environment that provides a basic shell.

Rust Setup

Instructions to install Rust are available here:

Getting started

For a Linux like environment the command looks like this:

curl — proto ‘=https’ — tlsv1.2 -sSf https://sh.rustup.rs | sh
Enter fullscreen mode Exit fullscreen mode

Gemini CLI

If not pre-installed you can download the Gemini CLI to interact with the source files and provide real-time assistance:

npm install -g @google/gemini-cli
Enter fullscreen mode Exit fullscreen mode

Testing the Gemini CLI Environment

Once you have all the tools and the correct Node.js version in place- you can test the startup of Gemini CLI. You will need to authenticate with a Key or your Google Account:

gemini
Enter fullscreen mode Exit fullscreen mode

Node Version Management

Gemini CLI needs a consistent, up to date version of Node. The nvm command can be used to get a standard Node environment:

GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions

Clone the Samples Repo and Setup the Basic Environment

Now that the Gemini CLI and the Rust installation has been validated from the base shell — you can clone the GitHub Repo with support scripts:

cd ~
git clone https://github.com/xbill9/sysutils-https-rust
Enter fullscreen mode Exit fullscreen mode

Then run set_env.sh from the cloned directory. The script will attempt to determine your shell environment and set the correct variables:

cd sysutils-https-rust
source set_env.sh
Enter fullscreen mode Exit fullscreen mode

Debugging API Permission Errors

If you did not set your environment variables or your Google Cloud Authentication expires you will get an error. The workaround is to re-authenticate:

gcloud auth login
Enter fullscreen mode Exit fullscreen mode

Another common error is that the environment variables are not set correctly. Go the the root directory and re-run the set_env.sh to set the variables:

cd ~/sysutils-https-rust
source set_env.sh
Enter fullscreen mode Exit fullscreen mode

Debugging and Logging with Rust

The environment variable RUST_LOG controls how verbose the logging from the Rust code will produce messages. Initially — set the variable to info:

export RUST_LOG=info
echo $RUST_LOG
info
Enter fullscreen mode Exit fullscreen mode

Rust Log Levels

These levels filter messages based on their severity, from most critical to least:

  • ERROR : Only error messages are logged.
  • WARN : Warning messages and higher (error) are logged.
  • INFO : Informational messages and higher (warn, error) are logged.
  • DEBUG : Debug messages and higher (info, warn, error) are logged.
  • TRACE : Trace messages and higher (debug, info, warn, error) are logged. This is the most verbose level.
  • OFF : Disables all logging.

Next Steps- Build Rust Sample Client Code

A basic native Rust client sample has been included in the GitHub repo. Change to the sample directory and validate the Cargo.toml file for the minimal sample:

cd xbill@penguin:~$ cd sysutils-https-rust/
Enter fullscreen mode Exit fullscreen mode

The Rust standard format file Cargo.toml contains details about the code:

[package]
name = "sysutils-https-rust"
version = "0.2.0"
edition = "2024"
description = "System Utilities MCP HTTP transport in Rust"
license = "MIT"
repository = "https://github.com/xbill9/sysutils-rust"

Enter fullscreen mode Exit fullscreen mode

Lint the code:

xbill@penguin:~/sysutils-https-rust$ make lint
Linting code...
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.14s
xbill@penguin:~/sysutils-https-rust$ 
Enter fullscreen mode Exit fullscreen mode

Test the final binary:

xbill@penguin:~/sysutils-https-rust$ make test
Running tests...
   Compiling sysutils-https-rust v0.2.0 (/home/xbill/sysutils-https-rust)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 1.35s
     Running unittests src/main.rs (target/debug/deps/sysutils_https_rust-58c1477ff8677c5b)

running 2 tests
test tests::test_schema_generation ... ok
test tests::test_get_system_info ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s

xbill@penguin:~/sysutils-https-rust$ 
Enter fullscreen mode Exit fullscreen mode

Build the release version with the Makefile :

xbill@penguin:~/sysutils-https-rust$ make release
Building Release...
    Finished `release` profile [optimized] target(s) in 0.27s
xbill@penguin:~/sysutils-https-rust$ 
Enter fullscreen mode Exit fullscreen mode

Then run the generated release Rust binary:

xbill@penguin:~/sysutils-https-rust$ make run
Running the Rust project...
    Finished `release` profile [optimized] target(s) in 0.08s
     Running `target/release/sysutils-https-rust`
{"timestamp":"2026-02-04T19:09:36.298522Z","level":"INFO","fields":{"message":"MCP Server listening on http://0.0.0.0:8080"},"target":"sysutils_https_rust"}
Enter fullscreen mode Exit fullscreen mode

Verify the Tool Locally

Once the tool has been built and run- leave the server running locally and open a new terminal window. Start Gemini CLI:

Then check that the tool is accessible via MCP:

> /mcp list
Configured MCP servers:

🟢 sysutils-https-rust - Ready (1 tool)
  Tools:
  - get_system_info

 > get_system_info
✦ I will read the src/main.rs file to understand the implementation and expected parameters of the get_system_info tool.

╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFile src/main.rs │
│ │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I will execute cargo run -- info to generate and display the system information report.
                                                                                                          │
✦ System Information Report
  =========================

  System Name: Debian GNU/Linux
  Kernel Version: 6.6.99-09070-g0245f6566c20
  OS Version: 12
  Host Name: penguin

  CPU Information
  ---
  Number of Cores: 12

  Memory Information
  ---
  Total Memory: 6410 MB
  Used Memory: 766 MB
  Total Swap: 0 MB
  Used Swap: 0 MB

  Disk Information
  ---
  Name: "/dev/vdc"
  File System: "btrfs"
  Total Space: 259 GB
  Available Space: 106 GB
  ---
  Name: "9p"
  File System: "9p"
  Total Space: 3 GB
  Available Space: 3 GB
  ---
  Name: "/dev/vdb"
  File System: "ext4"
  Total Space: 0 GB
  Available Space: 0 GB
  ---
  Name: "fonts"
  File System: "virtiofs"
  Total Space: 2 GB
  Available Space: 0 GB
  ---
  (Additional disk entries for "/dev/vdc" omitted for brevity)

Enter fullscreen mode Exit fullscreen mode

You can check the local server logging:

{"timestamp":"2026-02-04T19:10:31.803626Z","level":"TRACE","fields":{"message":"register resource","resource":"McpRequestId(Number(1))","http_request_id":0},"target":"rmcp::transport::streamable_http_server::session::local","span":{"id":"984b0854-ab01-4a0b-822a-9eb97181374f","name":"streamable_http_session"},"spans":[{"name":"streamable-http-session-984b0854-ab01-4a0b-822a-9eb97181374f","name":"transport_worker"},{"id":"984b0854-ab01-4a0b-822a-9eb97181374f","name":"streamable_http_session"}]}
{"timestamp":"2026-02-04T19:10:31.803647Z","level":"TRACE","fields":{"message":"new event","evt":"PeerMessage(Request(JsonRpcRequest { jsonrpc: JsonRpcVersion2_0, id: Number(1), request: ListToolsRequest(RequestOptionalParam { method: ListToolsRequestMethod, params: Some(PaginatedRequestParams { meta: None, cursor: None }), extensions: Extensions }) }))"},"target":"rmcp::service","span":{"name":"serve_inner"},"spans":[{"name":"serve_inner"}]}
{"timestamp":"2026-02-04T19:10:31.803663Z","level":"DEBUG","fields":{"message":"received request","id":"1","request":"ListToolsRequest(RequestOptionalParam { method: ListToolsRequestMethod, params: Some(PaginatedRequestParams { meta: None, cursor: None }), extensions: Extensions })"},"target":"rmcp::service","span":{"name":"serve_inner"},"spans":[{"name":"serve_inner"}]}
{"timestamp":"2026-02-04T19:10:31.803697Z","level":"DEBUG","fields":{"message":"response message","id":"1","result":"ListToolsResult(ListToolsResult { meta: None, next_cursor: None, tools: [Tool { name: \"get_system_info\", title: None, description: Some(\"Get a detailed system information report including kernel, cores, memory, and disk usage.\"), input_schema: {\"title\": String(\"GetSystemInfoRequest\"), \"type\": String(\"object\")}, output_schema: None, annotations: None, icons: None, meta: None }] })"},"target":"rmcp::service","span":{"name":"serve_inner"},"spans":[{"name":"serve_inner"}]}
{"timestamp":"2026-02-04T19:10:31.803721Z","level":"TRACE","fields":{"message":"new event","evt":"ToSink(Response(JsonRpcResponse { jsonrpc: JsonRpcVersion2_0, id: Number(1), result: ListToolsResult(ListToolsResult { meta: None, next_cursor: None, tools: [Tool { name: \"get_system_info\", title: None, description: Some(\"Get a detailed system information report including kernel, cores, memory, and disk usage.\"), input_schema: {\"title\": String(\"GetSystemInfoRequest\"), \"type\": String(\"object\")}, output_schema: None, annotations: None, icons: None, meta: None }] }) }))"},"target":"rmcp::service","span":{"name":"serve_inner"},"spans":[{"name":"serve_inner"}]}
{"timestamp":"2026-02-04T19:10:31.803766Z","level":"TRACE","fields":{"message":"unregister resource","resource":"McpRequestId(Number(1))","http_request_id":0},"target":"rmcp::transport::streamable_http_server::session::local","span":{"id":"984b0854-ab01-4a0b-822a-9eb97181374f","name":"streamable_http_session"},"spans":[{"name":"streamable-http-session-984b0854-ab01-4a0b-822a-9eb97181374f","name":"transport_worker"},{"id":"984b0854-ab01-4a0b-822a-9eb97181374f","name":"streamable_http_session"}]}
{"timestamp":"2026-02-04T19:10:31.803778Z","level":"DEBUG","fields":{"message":"close http request wise channel","http_request_id":0},"target":"rmcp::transport::streamable_http_server::session::local","span":{"id":"984b0854-ab01-4a0b-822a-9eb97181374f","name":"streamable_http_session"},"spans":[{"name":"streamable-http-session-984b0854-ab01-4a0b-822a-9eb97181374f","name":"transport_worker"},{"id":"984b0854-ab01-4a0b-822a-9eb97181374f","name":"streamable_http_session"}]}
Enter fullscreen mode Exit fullscreen mode

Deploying to Cloud Run

After the HTTP version of the tool has been tested locally — it can be deployed remotely to Google Cloud Run.

First- switch to the directory with the HTTP sample code:

cd ~/sysutils-https-rust
Enter fullscreen mode Exit fullscreen mode

Deploy the project to Google Cloud Run with the pre-built cloudbuild.yaml and Dockerfile:

xbill@penguin:~/sysutils-https-rust$ make clean
Cleaning the project...
     Removed 4364 files, 1.8GiB total
xbill@penguin:~/sysutils-https-rust$ make deploy
Enter fullscreen mode Exit fullscreen mode

The Cloud Build will start:

xbill@penguin:~/sysutils-https-rust$ make clean
Cleaning the project...
     Removed 4364 files, 1.8GiB total
xbill@penguin:~/sysutils-https-rust$ make deploy
Submitting build to Google Cloud Build...
Creating temporary archive of 13 file(s) totalling 82.2 KiB before compression.
Uploading tarball of [.] to [gs://comglitn_cloudbuild/source/1770232491.984554-d55504d5bee74f26864157aecae63a0d.tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/comglitn/locations/global/builds/fd9e1bcf-9020-4309-91c4-2e2bc3f5b22c].
Logs are available at [https://console.cloud.google.com/cloud-build/builds/fd9e1bcf-9020-4309-91c4-2e2bc3f5b22c?project=1056842563084].
Waiting for build to complete. Polling interval: 1 second(s).
------------------------------------------------------------ REMOTE BUILD OUTPUT -------------------------------------------------------------
starting build "fd9e1bcf-9020-4309-91c4-2e2bc3f5b22c"

Enter fullscreen mode Exit fullscreen mode

It can take 15–30 minutes to complete the build.

The cloud build needs to pull in all the Rust libraries in the build environment and generate the entire package from scratch:

Starting Step #1
Step #1: Already have image (with digest): gcr.io/cloud-builders/gcloud
Step #1: Deploying container to Cloud Run service [sysutils-https-rust] in project [comglitn] region [us-central1]
Step #1: Deploying...
Step #1: Setting IAM Policy.........done
Step #1: Creating Revision.......................................................done
Step #1: Routing traffic.....done
Step #1: Done.
Step #1: Service [sysutils-https-rust] revision [sysutils-https-rust-00003-t28] has been deployed and is serving 100 percent of traffic.
Step #1: Service URL: https://sysutils-https-rust-1056842563084.us-central1.run.app
Finished Step #1
PUSH
Enter fullscreen mode Exit fullscreen mode

When the build is complete- an endpoint will be returned. The service endpoint in this example is :

https://sysutils-https-rust-1056842563084.us-central1.run.app
Enter fullscreen mode Exit fullscreen mode

The actual endpoint will vary based on your project settings.

Review Service in Cloud Run

Navigate to the Google Cloud console and search for Cloud Run -

and then you can detailed information on the Cloud Run Service:

Cloud Logging

The remote server writes logs to stderr in standard JSON format. These logs are available from the deployed Cloud Run Service:

Validate the connection

Once you have the Endpoint — you can attempt a connection- navigate to in your browser:

https://sysutils-https-rust-1056842563084.us-central1.run.app
Enter fullscreen mode Exit fullscreen mode

You will need to adjust the exact URL to match the URL returned from Cloud Build.

You will get an error- this connection is expecting a message in the MCP format:

{"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"Parse error"}}
Enter fullscreen mode Exit fullscreen mode

Gemini CLI settings.json.cloudrun

Replace the default Gemini CLI configuration file —  settings.json with a pre-configured sample- settings.json.cloudrun to use the Cloud Run version of the connection:

{
    "mcpServers": {
    "sysutils-cloudrun-rust": {
       "httpUrl": "https://sysutils-https-rust-1056842563084.us-central1.run.app/mcp"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Copy the Cloud Run version of the Gemini CLI configuration file:

xbill@penguin:~/sysutils-https-rust$ 
cp settings.json.cloudrun settings.json
Enter fullscreen mode Exit fullscreen mode

Validation with Gemini CLI

The final connection test uses Gemini CLI as a MCP client with the deployed Cloud Run Service in Rust providing the MCP server. Startup Gemini CLI with the updated settings :

 > /mcp list
Configured MCP servers:

🟢 sysutils-cloudrun-rust - Ready (1 tool)
  Tools:
  - get_system_info

 > call mcp server get_system_info
✦ I will call the get_system_info tool to retrieve the detailed system information report.

✦ The system information report for the current environment is as follows:

    1 System Information Report
    2 =========================
    3
    4 System Name: Debian GNU/Linux
    5 Kernel Version: 4.4.0
    6 OS Version: 12
    7 Host Name: localhost
    8
    9 CPU Information
   10 ---------------
   11 Number of Cores: 2
   12
   13 Memory Information
   14 ------------------
   15 Total Memory: 1024 MB
   16 Used Memory: 5 MB
   17 Total Swap: 0 MB
   18 Used Swap: 0 MB
   19
   20 Disk Information
   21 ----------------
   22 Name: "none"
   23 File System: "overlay"
   24 Total Space: 8589934591 GB
   25 Available Space: 8589934591 GB
   26 ---
   27 Name: "none"
   28 File System: "overlay"
   29 Total Space: 8589934591 GB
   30 Available Space: 8589934591 GB
   31 ---
   32 Name: "none"
   33 File System: "overlay"
   34 Total Space: 8589934591 GB
   35 Available Space: 8589934591 GB
   36 ---
   37 Name: "none"
   38 File System: "overlay"
   39 Total Space: 0 GB
   40 Available Space: 0 GB
   41 ---
Enter fullscreen mode Exit fullscreen mode

Verify that the MCP tool is in fact running remotely in Cloud Run:

✦ The get_system_info tool is running inside a containerized or sandboxed environment that is separate from your current shell environment.

  We can see this by comparing the reports:
   * The MCP Tool reports Kernel version 4.4.0 and hostname localhost. This kernel version and the unusual disk reporting (8 exabytes) are
     characteristic of sandboxed runtimes like gVisor (commonly used in Google Cloud Run).
   * Your local shell is running on Kernel 6.6.99 with the hostname penguin (a typical ChromeOS Linux container).

  This confirms that while you are developing the code in this directory, the get_system_info tool you just invoked is executing within the
  sysutils-cloudrun-rust MCP server's specific runtime environment.

Enter fullscreen mode Exit fullscreen mode

Package Information on crates.io

The complete package is available on the Rust crates.io site:

crates.io: Rust Package Registry

Here is the package details page:

Summary

A complete Rust native system information utility was built and testing using Gemini CLI along with Rust libraries. This compiled Rust code was then called directly from the local environment and returned basic system information.

Then, the tool was wrapped in a container and deployed to Google Cloud Run. This cloud deployment was used to verify the environment in the remote Cloud Run server over the streaming HTTP MCP transport with a local copy of Gemini CLI.

Top comments (0)