DEV Community

xbill for Google Developer Experts

Posted on • Originally published at Medium on

MCP Development with Firestore, Ruby and Gemini CLI

Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with Ruby with a local development environment backed by a Firestore NOSQL database.


Image by Author

Why not just use Python?

Python has traditionally been the main coding language for ML and AI tools. One of the strengths of the MCP protocol is that the actual implementation details are independent of the development language. The reality is that not every project is coded in Python- and MCP allows you to use the latest AI approaches with other coding languages.

Ruby? For AI? Is this even possible?

The goal of this article is to provide a minimal viable basic working MCP stdio server in Ruby that can be run locally without any unneeded extra code or extensions. The official Ruby MCP SDK is here:

GitHub - modelcontextprotocol/ruby-sdk: The official Ruby SDK for the Model Context Protocol. Maintained in collaboration with Shopify.

What Is Ruby?

Ruby is a dynamic, general-purpose programming language known for its focus on simplicity and developer happiness. It is an open-source, object-oriented language that aims for an elegant syntax which is natural to read and easy to write, almost like English.

The full details of the language can be found here:

Ruby Programming Language

What is Ruby Gems?

RubyGems is a package manager for the Ruby programming language that provides a standard format for distributing Ruby programs and libraries.

The main download site is here:

RubyGems.org | your community gem host

Ruby Version Management

One of the downsides of the wide deployment of Ruby has been managing the language versions across platforms and maintaining a supported version. There are several Ruby version managers- a good starting point is rvm :

RVM: Ruby Version Manager - RVM Ruby Version Manager - Documentation

Install rvm :

xbill@penguin:~$ gpg --keyserver keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D69
56105BD0E739499BDB
gpg: directory '/home/xbill/.gnupg' created
gpg: keybox '/home/xbill/.gnupg/pubring.kbx' created
gpg: key 105BD0E739499BDB: 2 duplicate signatures removed
gpg: /home/xbill/.gnupg/trustdb.gpg: trustdb created
gpg: key 105BD0E739499BDB: public key "Piotr Kuczynski <piotr.kuczynski@gmail.com>" imported
gpg: key 3804BB82D39DC0E3: public key "Michal Papis (RVM signing) <mpapis@gmail.com>" imported
gpg: Total number processed: 2
gpg: imported: 2
xbill@penguin:~$ \curl -sSL https://get.rvm.io | bash -s stable
Downloading https://github.com/rvm/rvm/archive/1.29.12.tar.gz
Downloading https://github.com/rvm/rvm/releases/download/1.29.12/1.29.12.tar.gz.asc
gpg: Signature made Fri 15 Jan 2021 01:46:22 PM EST
gpg: using RSA key 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
gpg: Good signature from "Piotr Kuczynski <piotr.kuczynski@gmail.com>" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: 7D2B AF1C F37B 13E2 069D 6956 105B D0E7 3949 9BDB
GPG verified '/home/xbill/.rvm/archives/rvm-1.29.12.tgz'
Installing RVM to /home/xbill/.rvm/
    Adding rvm PATH line to /home/xbill/.profile /home/xbill/.mkshrc /home/xbill/.bashrc /home/xbill/.zshrc.
    Adding rvm loading line to /home/xbill/.profile /home/xbill/.bash_profile /home/xbill/.zlogin.
Installation of RVM in /home/xbill/.rvm/ is almost complete:
Enter fullscreen mode Exit fullscreen mode

Then download the latest Ruby- as of writing it is 3.4.8:

xbill@penguin:~$ source /home/xbill/.rvm/scripts/rvm
xbill@penguin:~$ rvm install 3.4.8
Searching for binary rubies, this might take some time.
No binary rubies available for: debian/12/x86_64/ruby-3.4.8.
Continuing with compilation. Please read 'rvm help mount' to get more information on binary rubies.
Checking requirements for debian.
Installing requirements for debian.
Updating system....
Enter fullscreen mode Exit fullscreen mode

What is FireStore?

Google Firestore, also known as Cloud Firestore is a part of the Google Firebase application development platform. It is fundamentally a cloud-hosted NoSQL database for storing and syncing data. Firestore can be directly accessed by mobile and web applications through native SDKs.

Firestore | Firebase

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

Ruby MCP Documentation

The official MCP GitHub Repo provides samples and documentation for getting started:

ruby-sdk/README.md at main · modelcontextprotocol/ruby-sdk

Where do I start?

The strategy for starting MCP development is a incremental step by step approach.

First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.

Then, a minimal Hello World Style Ruby MCP Server is built with stdio transport. This server is validated with Gemini CLI in the local environment.

This setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the Ruby MCP server both run in the same local environment.

Next- the basic MCP server is extended with Gemini CLI to add several new tools in standard code.

Setup the Basic Environment

At this point you should have a working Ruby environment and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:

cd ~
git clone https://github.com/xbill9/gemini-cli-codeassist
Enter fullscreen mode Exit fullscreen mode

Then run init.sh from the cloned directory.

The script will attempt to determine your shell environment and set the correct variables:

cd gemini-cli-codeassist
source init.sh
Enter fullscreen mode Exit fullscreen mode

If your session times out or you need to re-authenticate- you can run the set_env.sh script to reset your environment variables:

cd gemini-cli-codeassist
source set_env.sh
Enter fullscreen mode Exit fullscreen mode

Variables like PROJECT_ID need to be setup for use in the various build scripts- so the set_env script can be used to reset the environment if you time-out.

Hello World with STDIO Transport

One of the key features that the standard MCP libraries provide is abstracting various transport methods.

The high level MCP tool implementation is the same no matter what low level transport channel/method that the MCP Client uses to connect to a MCP Server.

The simplest transport that the SDK supports is the stdio (stdio/stdout) transport — which connects a locally running process. Both the MCP client and MCP Server must be running in the same environment.

The connection over stdio will look similar to this:

LOGGER.info "Starting MCP server: #{server.name} (v#{server.version})"
    transport = MCP::Server::Transports::StdioTransport.new(server)
    transport.open
Enter fullscreen mode Exit fullscreen mode

Gemfile

The Ruby Gemfile includes the MCP and logging gems:

# frozen_string_literal: true

Gem::Specification.new do |spec|
  spec.name = 'firestore-mcp-server'
  spec.version = '0.1.1'
  spec.authors = ['xbill']
  spec.email = ['xbill9@gmail.com']

  spec.summary = 'A Model Context Protocol (MCP) server for Google Cloud Firestore.'
  spec.description = 'Exposes Firestore operations (inventory management) as MCP tools over stdio.'
  spec.homepage = 'https://github.com/xbill9/gemini-cli-codeassist/firestore-mcp-server'
  spec.license = 'MIT'
  spec.required_ruby_version = '>= 3.1.0'
Enter fullscreen mode Exit fullscreen mode

Running the Ruby Code

First- switch the directory with the Ruby MCP sample code:

cd ~/gemini-cli-codeassist/firestore-stdio-ruby
Enter fullscreen mode Exit fullscreen mode

Run the install make target on the local system:

xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-ruby$ make install
Installing dependencies...
Bundle complete! 6 Gemfile dependencies, 56 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
1 installed gem you directly depend on is looking for funding.
  Run `bundle fund` for details
Enter fullscreen mode Exit fullscreen mode

To test the Ruby code:

xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-ruby$ make test
Running tests...
{"severity":"INFO","timestamp":"2026-01-07T17:51:44-05:00","progname":null,"message":"Firestore client initialized"}
{"severity":"INFO","timestamp":"2026-01-07T17:51:44-05:00","progname":null,"message":"GreetTool called with message: Hello, World!"}
.....

Finished in 0.00767 seconds (files took 0.64132 seconds to load)
5 examples, 0 failures

xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-ruby$
Enter fullscreen mode Exit fullscreen mode

To style check / lint the code:

xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-ruby$ make lint
Linting the code...
Inspecting 15 files
...............

15 files inspected, no offenses detected
xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-ruby$
Enter fullscreen mode Exit fullscreen mode

Gemini CLI settings.json

The default Gemini CLI settings.json has an entry for the Ruby source:

{
  "mcpServers": {
    "firestore-stdio-ruby": {
      "command": "ruby",
      "args": [
        "$HOME/gemini-cli-codeassist/firestore-stdio-ruby/main.rb"
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Review the Project with Gemini CLI

Start-up Gemini CLI and review the entire project:

> what does this project do?

✦ This project is a Ruby-based Model Context Protocol (MCP) server that connects to a Google Cloud Firestore database. It allows
  AI models (like Gemini or Claude) to interact with a "Cymbal Superstore" inventory database through a standardized interface.

  Key Functionalities:

   * Exposes Tools: It provides a set of tools reachable via standard input/output (stdio):
       * get_products: Lists all inventory items.
       * get_product_by_id: Fetches details of a specific item.
       * seed & reset: Populates or clears the database for testing.
       * check_db: Verifies database connectivity.
       * greet: A simple echo tool for testing.
   * Tech Stack: Built with Ruby using the mcp SDK and google-cloud-firestore gem.
   * Architecture: It follows a modular design with tools defined in lib/ and registered in main.rb.

  In short, it acts as a bridge, allowing an AI assistant to read from and write to your Firestore inventory database.
Enter fullscreen mode Exit fullscreen mode

Validation with Gemini CLI

Finally- Gemini CLI is restarted and the MCP connection over stdio to the Ruby Code is validated, The full Gemini CLI Session will start:

> /mcp list

> /mcp list

Configured MCP servers:

🟢 firestore-stdio-ruby - Ready (7 tools)
  Tools:
  - check_db
  - get_product_by_id
  - get_products
  - get_root
  - greet
  - reset
  - seed

> get_products

✦ The get_products tool returned a list of 34 products, including items like Green Tea, Jasmine Rice, Coffee Beans, and various
  snacks and staples. Is there a specific product you'd like more details on, or any other action you'd like me to perform?

Enter fullscreen mode Exit fullscreen mode

Extending the Ruby MCP Server with Gemini CLI

Now that the basic MCP functionality has been tested and verified with Gemini CLI- the Ruby server code can be extended with new MCP tools:

> add new MCP tools - one that searchs the products, 
one that suggests a menu, one that prints an inventory report.
Enter fullscreen mode Exit fullscreen mode

Gemini CLI will get right to work:

✦ I have successfully added the three new MCP tools: search_products, suggest_menu, and inventory_report. I've also registered
  them in main.rb and verified their functionality with a new test suite spec/new_tools_spec.rb, which passed.
Enter fullscreen mode Exit fullscreen mode

Restart Gemini CLI and check for the new MCP tools:

> /mcp list

Configured MCP servers:

🟢 firestore-stdio-ruby - Ready (10 tools)
  Tools:
  - inventory_report
  - search_products
  - suggest_menu

Enter fullscreen mode Exit fullscreen mode

The new MCP tools can be used in the current context:

> inventory_report

✦ The inventory report has been generated:

  Inventory Report
   - Total Unique Products: 34
   - Total Stock Quantity: 8,255
   - Total Inventory Value: $38,952.00

  Low Stock Alerts (< 10 items):
   - Walnuts
   - Wasabi Party Mix
   - Peanut Butter and Jelly Cups
   - Jalapeno Seasoning
   - Apple Juice

Enter fullscreen mode Exit fullscreen mode

and the search tool:

> search_tool Coffee

✦ The search for "coffee" returned the following product:

   * Product: Coffee Beans
   * Price: $6
   * Quantity: 375
   * ID: 37kWbZHTwg5nbrSD13PB
   * Image: product-images/coffeebeans.png

> search_tool milk

✦ The search for "milk" returned the following product:

   * Product: Milk
   * Price: $4
   * Quantity: 62
   * ID: ohLPGO1wvIX2tw5zW8AS
   * Image: product-images/milk.png
Enter fullscreen mode Exit fullscreen mode

and menu information:

> suggest_menu

✦ I will suggest a menu for you based on the available inventory.
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ suggest_menu (firestore-stdio-ruby MCP Server) {} │
│ │
│ Here is a suggested menu: │
│ - Sunflower Seeds ($2) │
│ - Eggs ($1) │
│ - Rice ($2) │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ Here is a suggested menu based on available items:

   * Appetizer: Sunflower Seeds ($2)
   * Main: Eggs ($1)
   * Side: Rice ($2)

> suggest_menu

✦ I will suggest another menu for you based on the available inventory.
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ suggest_menu (firestore-stdio-ruby MCP Server) {} │
│ │
│ Here is a suggested menu: │
│ - Shrimp ($4) │
│ - Milk ($4) │
│ - Whole Chicken ($10) │
│ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ Here is another suggested menu:

   * Appetizer: Shrimp ($4)
   * Drink: Milk ($4)
   * Main: Whole Chicken ($10)
Enter fullscreen mode Exit fullscreen mode

The information from the MCP tool execution comes back into the current Gemini CLI context. You can use the information returned from the tools along with the underlying Gemini Models:

✦ Based on the current inventory, you cannot directly make cappuccinos because they are not listed as an item, and there are no
  recipes provided in the codebase. However, you have the following key ingredients:

   * Coffee Beans: 375 units
   * Milk: 62 units

  A standard cappuccino typically requires a 1:1 ratio of espresso (from coffee beans) and steamed milk. Since you have 62 units
  of milk, that would be your limiting factor.

  Estimation:
   - Maximum Cappuccinos: 62 (assuming 1 unit of milk per cappuccino).
   - Gross Profit: Cannot be calculated as there is no selling price for a cappuccino or cost data for the ingredients.

> recommend a selling price for the cappuccinos

✦ Based on the current inventory and price points of existing products (which range from $1.00 to $10.00), I recommend a selling
  price of $5.00 to $6.00 for a cappuccino.

  Reasoning:
   * Ingredient Value: Your Coffee Beans are priced at $6.00 and Milk at $4.00.
   * Market Positioning: In your test specifications, Black Coffee is listed at $4.00. Since a cappuccino requires additional
     preparation (steaming milk) and is considered a premium drink, it should be priced higher than standard coffee.
   * Consistency: A price of $5.00 aligns with the median price of items in your inventory, keeping it accessible while ensuring
     a higher margin than basic ingredients.
Enter fullscreen mode Exit fullscreen mode

Summary

The strategy for using Ruby for MCP development with Gemini CLI was validated with a incremental step by step approach.

A minimal stdio transport MCP Server was started from Ruby source code and validated with Gemini CLI running as a MCP client in the same local environment.

Gemini CLI was then used to extend the sample Ruby code with several MCP tools and use these tools inside the context for the underlying LLM.

This approach can be extended to more complex deployments using other MCP transports and Cloud based options.

Top comments (0)