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.
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:
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:
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:
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....
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.
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
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
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:
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
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
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
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
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'
Running the Ruby Code
First- switch the directory with the Ruby MCP sample code:
cd ~/gemini-cli-codeassist/firestore-stdio-ruby
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
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$
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$
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"
]
}
}
}
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.
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?
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.
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.
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
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
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
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)
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.
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)